rufus 0.7 → 0.8
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.
- checksums.yaml +8 -8
- data/RufusApp/RufusApp/en.lproj/RUViewController.xib +11 -19
- data/config.yml +4 -3
- data/features/step_definitions/driver_steps.rb +1 -1
- data/features/step_definitions/view_steps.rb +6 -0
- data/features/support/screens/home_page.rb +1 -0
- data/features/view.feature +8 -0
- data/lib/rufus.rb +5 -5
- data/lib/rufus/accessors/view.rb +7 -8
- data/lib/rufus/driver.rb +41 -118
- data/lib/rufus/drivers/driver_base.rb +212 -0
- data/lib/rufus/drivers/driver_factory.rb +41 -0
- data/lib/rufus/drivers/iOS_device.rb +4 -4
- data/lib/rufus/drivers/iOS_faster_device.rb +37 -0
- data/lib/rufus/drivers/iOS_faster_simulator.rb +37 -0
- data/lib/rufus/drivers/iOS_simulator.rb +4 -6
- data/lib/rufus/parser.rb +81 -0
- data/rufus.gemspec +1 -1
- data/spec/drivers_specs/driver_factory_spec.rb +38 -0
- data/spec/drivers_specs/driver_spec.rb +3 -372
- data/spec/drivers_specs/iOS_device_spec.rb +70 -12
- data/spec/drivers_specs/iOS_faster_device_spec.rb +105 -0
- data/spec/drivers_specs/iOS_faster_simulator_spec.rb +113 -0
- data/spec/drivers_specs/iOS_simulator_spec.rb +69 -13
- data/spec/parser_spec.rb +116 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/view_spec.rb +14 -22
- metadata +11 -2
@@ -0,0 +1,212 @@
|
|
1
|
+
module Rufus
|
2
|
+
module Drivers
|
3
|
+
class DriverBase
|
4
|
+
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
def capabilities; raise Exception; end
|
8
|
+
|
9
|
+
def start
|
10
|
+
selenium.get url
|
11
|
+
end
|
12
|
+
|
13
|
+
def quit
|
14
|
+
selenium.quit
|
15
|
+
@selenium_driver = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def server_url
|
19
|
+
@url
|
20
|
+
end
|
21
|
+
|
22
|
+
def find(locator)
|
23
|
+
how = locator.keys[0].to_sym
|
24
|
+
what = locator[how]
|
25
|
+
begin
|
26
|
+
selenium.find_element(how, what)
|
27
|
+
rescue Selenium::WebDriver::Error::NoSuchElementError
|
28
|
+
return nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def contains_name_key?(locator)
|
33
|
+
locator.keys[0].to_s.eql?('name')
|
34
|
+
end
|
35
|
+
|
36
|
+
def cells(locator)
|
37
|
+
element = find(locator)
|
38
|
+
raise 'Expected view to be of type UIATableView' unless element.tag_name.eql? 'UIATableView'
|
39
|
+
element.find_elements(:tag_name, 'UIATableCell')
|
40
|
+
end
|
41
|
+
|
42
|
+
def exists?(locator)
|
43
|
+
not find(locator).nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def click(locator)
|
47
|
+
find(locator).click
|
48
|
+
end
|
49
|
+
|
50
|
+
def press_button name
|
51
|
+
click(:name => name)
|
52
|
+
end
|
53
|
+
|
54
|
+
def enabled?(locator)
|
55
|
+
find(locator).enabled?
|
56
|
+
end
|
57
|
+
|
58
|
+
def displayed?(locator)
|
59
|
+
find(locator).displayed?
|
60
|
+
end
|
61
|
+
|
62
|
+
def text(locator)
|
63
|
+
find(locator).text
|
64
|
+
end
|
65
|
+
|
66
|
+
def class(locator)
|
67
|
+
find(locator).tag_name
|
68
|
+
end
|
69
|
+
|
70
|
+
def orientation
|
71
|
+
selenium.orientation.to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
def rotate(orientation)
|
75
|
+
selenium.rotate orientation
|
76
|
+
end
|
77
|
+
|
78
|
+
def type(keys, name)
|
79
|
+
element = find(:name => name)
|
80
|
+
element.click
|
81
|
+
sleep 1
|
82
|
+
element.send_keys keys
|
83
|
+
end
|
84
|
+
|
85
|
+
def sequence(*names, times)
|
86
|
+
timed_sequence(names, times, 1)
|
87
|
+
end
|
88
|
+
|
89
|
+
def buttons
|
90
|
+
buttons = []
|
91
|
+
elements = elements_by_tag 'UIAButton'
|
92
|
+
elements.each do |element|
|
93
|
+
buttons << element.text
|
94
|
+
end
|
95
|
+
buttons
|
96
|
+
end
|
97
|
+
|
98
|
+
def text_fields
|
99
|
+
fields = []
|
100
|
+
elements = elements_by_tag 'UIATextField'
|
101
|
+
elements.each do |element|
|
102
|
+
fields << element.text
|
103
|
+
end
|
104
|
+
fields
|
105
|
+
end
|
106
|
+
|
107
|
+
def labels
|
108
|
+
labels = []
|
109
|
+
elements = elements_by_tag 'UIAStaticText'
|
110
|
+
elements.each do |element|
|
111
|
+
labels << element.text
|
112
|
+
end
|
113
|
+
labels
|
114
|
+
end
|
115
|
+
|
116
|
+
def timed_sequence(names, times, seconds)
|
117
|
+
current = 0
|
118
|
+
until current == times
|
119
|
+
names.each do |name|
|
120
|
+
click(:name => name)
|
121
|
+
sleep seconds
|
122
|
+
|
123
|
+
end
|
124
|
+
current += 1
|
125
|
+
puts "sequence #{current} completed"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def find_alert(locator)
|
130
|
+
alert = nil
|
131
|
+
all_elements.each do |element|
|
132
|
+
if is_alert?(element)
|
133
|
+
alert = element if match?(element, locator[:name])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
alert
|
137
|
+
end
|
138
|
+
|
139
|
+
def click_alert(button)
|
140
|
+
if alert_shown?
|
141
|
+
click_alert_button(button)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def alert_shown?
|
146
|
+
all_elements.each do |element|
|
147
|
+
if is_alert?(element)
|
148
|
+
return true
|
149
|
+
end
|
150
|
+
end
|
151
|
+
false
|
152
|
+
end
|
153
|
+
|
154
|
+
def class_for(element)
|
155
|
+
element.tag_name
|
156
|
+
end
|
157
|
+
|
158
|
+
def match?(element, name)
|
159
|
+
element.attribute(:name).eql? name
|
160
|
+
end
|
161
|
+
|
162
|
+
def page_source
|
163
|
+
selenium.page_source
|
164
|
+
end
|
165
|
+
|
166
|
+
def all_elements
|
167
|
+
elements_by_tag('UIAElement')
|
168
|
+
end
|
169
|
+
|
170
|
+
def elements_by_tag(name)
|
171
|
+
selenium.find_elements(:tag_name, name)
|
172
|
+
end
|
173
|
+
|
174
|
+
def scroll_to(locator)
|
175
|
+
id = find(locator).ref
|
176
|
+
selenium.execute_script 'mobile: scrollTo', {'element' => id}
|
177
|
+
end
|
178
|
+
|
179
|
+
def screenshot(name)
|
180
|
+
selenium.save_screenshot name
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
def url
|
186
|
+
if @config["appium_url"].nil? || @config["appium_url"].eql?("")
|
187
|
+
'http://127.0.0.1:4723/wd/hub'
|
188
|
+
else
|
189
|
+
@config["appium_url"]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def click_alert_button(button)
|
194
|
+
all_elements.each do |element|
|
195
|
+
element.click if is_table_view_cell?(element) && match?(element, button)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def is_alert?(element)
|
200
|
+
class_for(element).eql?('UIAAlert')
|
201
|
+
end
|
202
|
+
|
203
|
+
def is_table_view_cell?(element)
|
204
|
+
class_for(element).eql?('UIATableCell')
|
205
|
+
end
|
206
|
+
|
207
|
+
def selenium
|
208
|
+
@selenium_driver ||= Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => url)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rufus/drivers/iOS_device'
|
2
|
+
require 'rufus/drivers/iOS_simulator'
|
3
|
+
require 'rufus/drivers/iOS_faster_device'
|
4
|
+
require 'rufus/drivers/iOS_faster_simulator'
|
5
|
+
|
6
|
+
module Rufus
|
7
|
+
module Drivers
|
8
|
+
class DriverFactory
|
9
|
+
|
10
|
+
def self.driver_for(config)
|
11
|
+
return ios_driver_for(config) if is_ios? config
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def self.ios_driver_for(config)
|
17
|
+
return ios_physical_driver_for(config) if use_physical(config)
|
18
|
+
ios_simulator_driver_for(config)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.is_ios?(config)
|
22
|
+
config["browser"].eql?("iOS")
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.use_physical(config)
|
26
|
+
return config["use_physical"] unless config["use_physical"].nil?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.ios_physical_driver_for(config)
|
31
|
+
return Rufus::Drivers::IOS_FasterDevice.new(config) if config["optimized"]
|
32
|
+
Rufus::Drivers::IOS_Device.new(config)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.ios_simulator_driver_for(config)
|
36
|
+
return Rufus::Drivers::IOS_FasterSimulator.new(config) if config["optimized"]
|
37
|
+
Rufus::Drivers::IOS_Simulator.new(config)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
require 'selenium-webdriver'
|
2
|
+
require 'rufus/drivers/driver_base'
|
2
3
|
|
3
4
|
module Rufus
|
4
5
|
module Drivers
|
5
|
-
class IOS_Device
|
6
|
+
class IOS_Device < Rufus::Drivers::DriverBase
|
6
7
|
|
7
|
-
def
|
8
|
+
def initialize(config)
|
8
9
|
@config = config
|
9
|
-
Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => url)
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def capabilities
|
13
13
|
{
|
14
14
|
'browserName' => @config["browser"],
|
15
15
|
'platform' => @config["platform"],
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rufus/drivers/iOS_device'
|
2
|
+
require 'rufus/parser'
|
3
|
+
|
4
|
+
module Rufus
|
5
|
+
module Drivers
|
6
|
+
class IOS_FasterDevice < IOS_Device
|
7
|
+
|
8
|
+
def exists?(locator)
|
9
|
+
if contains_name_key? locator
|
10
|
+
Rufus::Parser.new(page_source).exists?(locator[:name])
|
11
|
+
else
|
12
|
+
super locator
|
13
|
+
end
|
14
|
+
end
|
15
|
+
def enabled?(locator)
|
16
|
+
if contains_name_key? locator
|
17
|
+
Rufus::Parser.new(page_source).enabled?(locator[:name])
|
18
|
+
else
|
19
|
+
super locator
|
20
|
+
end
|
21
|
+
end
|
22
|
+
def displayed?(locator)
|
23
|
+
if contains_name_key? locator
|
24
|
+
Rufus::Parser.new(page_source).displayed?(locator[:name])
|
25
|
+
else
|
26
|
+
super locator
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def text(locator)
|
30
|
+
Rufus::Parser.new(page_source).value(locator[:name])
|
31
|
+
end
|
32
|
+
def class(locator)
|
33
|
+
Rufus::Parser.new(page_source).class_for(locator[:name])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rufus/drivers/iOS_simulator'
|
2
|
+
require 'rufus/parser'
|
3
|
+
|
4
|
+
module Rufus
|
5
|
+
module Drivers
|
6
|
+
class IOS_FasterSimulator < IOS_Simulator
|
7
|
+
|
8
|
+
def exists?(locator)
|
9
|
+
if contains_name_key? locator
|
10
|
+
Rufus::Parser.new(page_source).exists?(locator[:name])
|
11
|
+
else
|
12
|
+
super locator
|
13
|
+
end
|
14
|
+
end
|
15
|
+
def enabled?(locator)
|
16
|
+
if contains_name_key? locator
|
17
|
+
Rufus::Parser.new(page_source).enabled?(locator[:name])
|
18
|
+
else
|
19
|
+
super locator
|
20
|
+
end
|
21
|
+
end
|
22
|
+
def displayed?(locator)
|
23
|
+
if contains_name_key? locator
|
24
|
+
Rufus::Parser.new(page_source).displayed?(locator[:name])
|
25
|
+
else
|
26
|
+
super locator
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def text(locator)
|
30
|
+
Rufus::Parser.new(page_source).value(locator[:name])
|
31
|
+
end
|
32
|
+
def class(locator)
|
33
|
+
Rufus::Parser.new(page_source).class_for(locator[:name])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,17 +1,15 @@
|
|
1
1
|
require 'selenium-webdriver'
|
2
|
+
require 'rufus/drivers/driver_base'
|
2
3
|
|
3
4
|
module Rufus
|
4
5
|
module Drivers
|
5
|
-
class IOS_Simulator
|
6
|
+
class IOS_Simulator < Rufus::Drivers::DriverBase
|
6
7
|
|
7
|
-
def
|
8
|
+
def initialize(config)
|
8
9
|
@config = config
|
9
|
-
Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => url)
|
10
|
-
#driver(url)
|
11
10
|
end
|
12
11
|
|
13
|
-
|
14
|
-
def self.capabilities
|
12
|
+
def capabilities
|
15
13
|
{
|
16
14
|
'browserName' => @config["browser"],
|
17
15
|
'platform' => @config["platform"],
|
data/lib/rufus/parser.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'json'
|
2
|
+
module Rufus
|
3
|
+
class Parser
|
4
|
+
|
5
|
+
attr_reader :screen_data
|
6
|
+
|
7
|
+
def initialize(json)
|
8
|
+
@screen_data = JSON.parse(json)
|
9
|
+
end
|
10
|
+
|
11
|
+
def class_for(label)
|
12
|
+
view_by_label(label)['type'] if exists?(label)
|
13
|
+
end
|
14
|
+
|
15
|
+
def value(label)
|
16
|
+
view_by_label(label)['value'] if exists?(label)
|
17
|
+
end
|
18
|
+
|
19
|
+
def width(label)
|
20
|
+
view_by_label(label)['rect']['size']['width'] if exists?(label)
|
21
|
+
end
|
22
|
+
|
23
|
+
def height(label)
|
24
|
+
view_by_label(label)['rect']['size']['height'] if exists?(label)
|
25
|
+
end
|
26
|
+
|
27
|
+
def x_pos(label)
|
28
|
+
view_by_label(label)['rect']['origin']['x'] if exists?(label)
|
29
|
+
end
|
30
|
+
|
31
|
+
def y_pos(label)
|
32
|
+
view_by_label(label)['rect']['origin']['y'] if exists?(label)
|
33
|
+
end
|
34
|
+
|
35
|
+
def label_for(label)
|
36
|
+
view_by_label(label)['label'] if exists?(label)
|
37
|
+
end
|
38
|
+
|
39
|
+
def enabled?(label)
|
40
|
+
view = view_by_label(label)
|
41
|
+
return false if view.nil?
|
42
|
+
view['enabled']
|
43
|
+
end
|
44
|
+
|
45
|
+
def displayed?(label)
|
46
|
+
view = view_by_label(label)
|
47
|
+
return false if view.nil?
|
48
|
+
view_by_label(label)['visible']
|
49
|
+
end
|
50
|
+
|
51
|
+
def child_count(label)
|
52
|
+
view_by_label(label)['children'].count if found(label)
|
53
|
+
end
|
54
|
+
|
55
|
+
def view_by_label(label)
|
56
|
+
@found_view = nil
|
57
|
+
view_data_for(@screen_data, label)
|
58
|
+
@found_view
|
59
|
+
end
|
60
|
+
|
61
|
+
def view_data_for(json, label)
|
62
|
+
if json['name'].eql?(label)
|
63
|
+
@found_view = json
|
64
|
+
else
|
65
|
+
if json['children'].count > 0
|
66
|
+
json['children'].each do |child|
|
67
|
+
view_data_for(child, label)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def exists?(label)
|
74
|
+
if view_by_label(label).nil?
|
75
|
+
false
|
76
|
+
else
|
77
|
+
view_by_label(label)['name'].eql?(label)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|