calabash-cucumber 0.9.163.pre6 → 0.9.163.pre7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/calabash-cucumber.gemspec +1 -1
- data/lib/calabash-cucumber/actions/instruments_actions.rb +135 -0
- data/lib/calabash-cucumber/actions/playback_actions.rb +104 -0
- data/lib/calabash-cucumber/connection.rb +16 -0
- data/lib/calabash-cucumber/connection_helpers.rb +17 -0
- data/lib/calabash-cucumber/core.rb +80 -553
- data/lib/calabash-cucumber/failure_helpers.rb +44 -0
- data/lib/calabash-cucumber/http_helpers.rb +102 -0
- data/lib/calabash-cucumber/ios7_operations.rb +46 -31
- data/lib/calabash-cucumber/keyboard_helpers.rb +26 -16
- data/lib/calabash-cucumber/launcher.rb +42 -8
- data/lib/calabash-cucumber/map.rb +28 -0
- data/lib/calabash-cucumber/operations.rb +0 -4
- data/lib/calabash-cucumber/playback_helpers.rb +200 -0
- data/lib/calabash-cucumber/query_helpers.rb +32 -0
- data/lib/calabash-cucumber/resources/double_tap_ios5_ipad.base64 +15 -0
- data/lib/calabash-cucumber/resources/double_tap_ios5_iphone.base64 +15 -0
- data/lib/calabash-cucumber/resources/double_tap_ios6_ipad.base64 +22 -0
- data/lib/calabash-cucumber/resources/double_tap_ios6_iphone.base64 +22 -0
- data/lib/calabash-cucumber/resources/swipe_down_ios5_iphone.base64 +31 -18
- data/lib/calabash-cucumber/resources/swipe_down_ios6_ipad.base64 +25 -0
- data/lib/calabash-cucumber/resources/swipe_down_ios6_iphone.base64 +25 -0
- data/lib/calabash-cucumber/resources/swipe_left_ios5_iphone.base64 +34 -79
- data/lib/calabash-cucumber/resources/swipe_left_ios6_ipad.base64 +28 -0
- data/lib/calabash-cucumber/resources/swipe_left_ios6_iphone.base64 +28 -0
- data/lib/calabash-cucumber/resources/swipe_right_ios6_ipad.base64 +25 -0
- data/lib/calabash-cucumber/resources/swipe_right_ios6_iphone.base64 +25 -0
- data/lib/calabash-cucumber/resources/swipe_up_ios5_iphone.base64 +28 -34
- data/lib/calabash-cucumber/resources/swipe_up_ios6_ipad.base64 +25 -0
- data/lib/calabash-cucumber/resources/swipe_up_ios6_iphone.base64 +25 -0
- data/lib/calabash-cucumber/resources/touch_hold_ios5_ipad.base64 +9 -0
- data/lib/calabash-cucumber/resources/touch_hold_ios5_iphone.base64 +9 -0
- data/lib/calabash-cucumber/resources/touch_hold_ios6_ipad.base64 +9 -0
- data/lib/calabash-cucumber/resources/touch_hold_ios6_iphone.base64 +9 -0
- data/lib/calabash-cucumber/rotation_helpers.rb +112 -0
- data/lib/calabash-cucumber/status_bar_helpers.rb +30 -0
- data/lib/calabash-cucumber/tests_helpers.rb +3 -42
- data/lib/calabash-cucumber/uia.rb +8 -7
- data/lib/calabash-cucumber/version.rb +2 -2
- data/lib/calabash-cucumber/wait_helpers.rb +19 -2
- metadata +31 -4
@@ -0,0 +1,44 @@
|
|
1
|
+
module Calabash
|
2
|
+
module Cucumber
|
3
|
+
module FailureHelpers
|
4
|
+
|
5
|
+
def screenshot(options={:prefix => nil, :name => nil})
|
6
|
+
prefix = options[:prefix]
|
7
|
+
name = options[:name]
|
8
|
+
|
9
|
+
@@screenshot_count ||= 0
|
10
|
+
res = http({:method => :get, :path => 'screenshot'})
|
11
|
+
prefix = prefix || ENV['SCREENSHOT_PATH'] || ""
|
12
|
+
if name.nil?
|
13
|
+
name = "screenshot"
|
14
|
+
else
|
15
|
+
if File.extname(name).downcase == ".png"
|
16
|
+
name = name.split(".png")[0]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
path = "#{prefix}#{name}_#{@@screenshot_count}.png"
|
21
|
+
File.open(path, 'wb') do |f|
|
22
|
+
f.write res
|
23
|
+
end
|
24
|
+
@@screenshot_count += 1
|
25
|
+
path
|
26
|
+
end
|
27
|
+
|
28
|
+
def screenshot_embed(options={:prefix => nil, :name => nil, :label => nil})
|
29
|
+
path = screenshot(options)
|
30
|
+
embed(path, "image/png", options[:label] || File.basename(path))
|
31
|
+
end
|
32
|
+
|
33
|
+
def screenshot_and_raise(msg, options={:prefix => nil, :name => nil, :label => nil})
|
34
|
+
screenshot_embed(options)
|
35
|
+
raise(msg)
|
36
|
+
end
|
37
|
+
|
38
|
+
def fail(msg="Error. Check log for details.", options={:prefix => nil, :name => nil, :label => nil})
|
39
|
+
screenshot_and_raise(msg, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'httpclient'
|
2
|
+
|
3
|
+
module Calabash
|
4
|
+
module Cucumber
|
5
|
+
module HTTPHelpers
|
6
|
+
|
7
|
+
CAL_HTTP_RETRY_COUNT=3
|
8
|
+
RETRYABLE_ERRORS = [HTTPClient::TimeoutError,
|
9
|
+
HTTPClient::KeepAliveDisconnected,
|
10
|
+
Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ECONNABORTED,
|
11
|
+
Errno::ETIMEDOUT]
|
12
|
+
|
13
|
+
|
14
|
+
def http(options, data=nil)
|
15
|
+
options[:uri] = url_for(options[:path])
|
16
|
+
options[:method] = options[:method] || :get
|
17
|
+
if data
|
18
|
+
if options[:raw]
|
19
|
+
options[:body] = data
|
20
|
+
else
|
21
|
+
options[:body] = data.to_json
|
22
|
+
end
|
23
|
+
end
|
24
|
+
res = make_http_request(options)
|
25
|
+
res.force_encoding("UTF-8") if res.respond_to?(:force_encoding)
|
26
|
+
res
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def url_for(verb)
|
31
|
+
url = URI.parse(ENV['DEVICE_ENDPOINT']|| "http://localhost:37265")
|
32
|
+
path = url.path
|
33
|
+
if path.end_with? "/"
|
34
|
+
path = "#{path}#{verb}"
|
35
|
+
else
|
36
|
+
path = "#{path}/#{verb}"
|
37
|
+
end
|
38
|
+
url.path = path
|
39
|
+
url
|
40
|
+
end
|
41
|
+
|
42
|
+
def make_http_request(options)
|
43
|
+
|
44
|
+
body = nil
|
45
|
+
retryable_errors = options[:retryable_errors] || RETRYABLE_ERRORS
|
46
|
+
CAL_HTTP_RETRY_COUNT.times do |count|
|
47
|
+
previous_debug_dev = nil
|
48
|
+
begin
|
49
|
+
if not @http
|
50
|
+
@http = init_request(options)
|
51
|
+
end
|
52
|
+
if options[:debug] || (ENV['DEBUG_HTTP'] == '1' && options[:debug] != false)
|
53
|
+
previous_debug_dev = @http.debug_dev
|
54
|
+
@http.debug_dev = $stdout
|
55
|
+
end
|
56
|
+
if options[:method] == :post
|
57
|
+
body = @http.post(options[:uri], options[:body]).body
|
58
|
+
else
|
59
|
+
body = @http.get(options[:uri], options[:body]).body
|
60
|
+
end
|
61
|
+
if options[:debug] || (ENV['DEBUG_HTTP'] == '1' && options[:debug] != false)
|
62
|
+
@http.debug_dev = previous_debug_dev
|
63
|
+
end
|
64
|
+
break
|
65
|
+
rescue Exception => e
|
66
|
+
|
67
|
+
if retryable_errors.include?(e) || retryable_errors.any? { |c| e.is_a?(c) }
|
68
|
+
|
69
|
+
if count < CAL_HTTP_RETRY_COUNT-1
|
70
|
+
if e.is_a?(HTTPClient::TimeoutError)
|
71
|
+
sleep(3)
|
72
|
+
else
|
73
|
+
sleep(0.5)
|
74
|
+
end
|
75
|
+
@http.reset_all
|
76
|
+
@http=nil
|
77
|
+
STDOUT.write "Retrying.. #{e.class}: (#{e})\n"
|
78
|
+
STDOUT.flush
|
79
|
+
else
|
80
|
+
puts "Failing... #{e.class}"
|
81
|
+
raise e
|
82
|
+
end
|
83
|
+
else
|
84
|
+
raise e
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
body
|
90
|
+
end
|
91
|
+
|
92
|
+
def init_request(url=nil)
|
93
|
+
http = HTTPClient.new
|
94
|
+
http.connect_timeout = 30
|
95
|
+
http.send_timeout = 30
|
96
|
+
http.receive_timeout = 30
|
97
|
+
http
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'calabash-cucumber/launcher'
|
2
2
|
require 'calabash-cucumber/uia'
|
3
|
-
|
3
|
+
require 'calabash-cucumber/actions/instruments_actions'
|
4
|
+
require 'calabash-cucumber/actions/playback_actions'
|
4
5
|
|
5
6
|
module Calabash
|
6
7
|
module Cucumber
|
@@ -60,42 +61,56 @@ module Calabash
|
|
60
61
|
[to_result]
|
61
62
|
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
def double_tap_ios7(options)
|
65
|
+
ui_query = options[:query]
|
66
|
+
offset = options[:offset]
|
67
|
+
if ui_query.nil?
|
68
|
+
uia_double_tap_offset(offset)
|
69
|
+
else
|
70
|
+
el_to_swipe = find_and_normalize_or_raise(ui_query)
|
71
|
+
offset = point_from(el_to_swipe, options)
|
72
|
+
uia_double_tap_offset(offset)
|
73
|
+
[el_to_swipe]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def two_finger_tap_ios7(options)
|
78
|
+
ui_query = options[:query]
|
79
|
+
offset = options[:offset]
|
80
|
+
if ui_query.nil?
|
81
|
+
uia_two_finger_tap_offset(offset)
|
82
|
+
else
|
83
|
+
el_to_swipe = find_and_normalize_or_raise(ui_query)
|
84
|
+
offset = point_from(el_to_swipe, options)
|
85
|
+
uia_two_finger_tap_offset(offset)
|
86
|
+
[el_to_swipe]
|
87
|
+
end
|
68
88
|
end
|
69
89
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
90
|
+
def flick_ios7(options, delta)
|
91
|
+
ui_query = options[:query]
|
92
|
+
offset = options[:offset]
|
93
|
+
if ui_query.nil?
|
94
|
+
uia_flick_offset(offset, add_offset(offset, delta))
|
74
95
|
else
|
75
|
-
|
96
|
+
el_to_swipe = find_and_normalize_or_raise(ui_query)
|
97
|
+
offset = point_from(el_to_swipe, options)
|
98
|
+
uia_flick_offset(offset, add_offset(offset, delta))
|
99
|
+
[el_to_swipe]
|
76
100
|
end
|
77
101
|
end
|
78
102
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
rect['center_x'] = screen_size[:height] - rect['center_y']
|
91
|
-
rect['center_y'] = cx
|
92
|
-
when :up
|
93
|
-
cy = rect['center_y']
|
94
|
-
cx = rect['center_x']
|
95
|
-
rect['center_y'] = screen_size[:height] - cy
|
96
|
-
rect['center_x'] = screen_size[:width] - cx
|
97
|
-
else
|
98
|
-
# no-op by design.
|
103
|
+
def touch_hold_ios7(options)
|
104
|
+
ui_query = options[:query]
|
105
|
+
offset = options[:offset]
|
106
|
+
duration = options[:duration] || 4
|
107
|
+
if ui_query.nil?
|
108
|
+
uia_touch_hold_offset(duration, offset)
|
109
|
+
else
|
110
|
+
el_to_swipe = find_and_normalize_or_raise(ui_query)
|
111
|
+
offset = point_from(el_to_swipe, options)
|
112
|
+
uia_touch_hold_offset(duration, offset)
|
113
|
+
[el_to_swipe]
|
99
114
|
end
|
100
115
|
end
|
101
116
|
|
@@ -1,21 +1,23 @@
|
|
1
|
+
require 'calabash-cucumber/core'
|
1
2
|
require 'calabash-cucumber/tests_helpers'
|
3
|
+
require 'calabash-cucumber/playback_helpers'
|
2
4
|
|
3
5
|
module Calabash
|
4
6
|
module Cucumber
|
5
7
|
module KeyboardHelpers
|
6
|
-
include Calabash::Cucumber::Core
|
7
8
|
include Calabash::Cucumber::TestsHelpers
|
9
|
+
include Calabash::Cucumber::PlaybackHelpers
|
8
10
|
|
9
11
|
KEYPLANE_NAMES = {
|
10
|
-
:small_letters =>
|
11
|
-
:capital_letters =>
|
12
|
-
:numbers_and_punctuation =>
|
13
|
-
:first_alternate =>
|
14
|
-
:numbers_and_punctuation_alternate =>
|
12
|
+
:small_letters => 'small-letters',
|
13
|
+
:capital_letters => 'capital-letters',
|
14
|
+
:numbers_and_punctuation => 'numbers-and-punctuation',
|
15
|
+
:first_alternate => 'first-alternate',
|
16
|
+
:numbers_and_punctuation_alternate => 'numbers-and-punctuation-alternate'
|
15
17
|
}
|
16
18
|
|
17
19
|
|
18
|
-
|
20
|
+
UIA_SUPPORTED_CHARS = {
|
19
21
|
'Dictation' => nil,
|
20
22
|
'Shift' => nil,
|
21
23
|
'Delete' => '\b',
|
@@ -32,11 +34,11 @@ module Calabash
|
|
32
34
|
# 'Return'
|
33
35
|
def keyboard_enter_char(chr, should_screenshot=true)
|
34
36
|
#map(nil, :keyboard, load_playback_data("touch_done"), chr)
|
35
|
-
if
|
37
|
+
if uia?
|
36
38
|
if chr.length == 1
|
37
39
|
uia_type_string chr
|
38
40
|
else
|
39
|
-
code =
|
41
|
+
code = UIA_SUPPORTED_CHARS[chr]
|
40
42
|
if code
|
41
43
|
uia_type_string code
|
42
44
|
else
|
@@ -46,7 +48,7 @@ module Calabash
|
|
46
48
|
res = {'results' => []}
|
47
49
|
else
|
48
50
|
res = http({:method => :post, :path => 'keyboard'},
|
49
|
-
{:key => chr, :events => load_playback_data(
|
51
|
+
{:key => chr, :events => load_playback_data('touch_done')})
|
50
52
|
res = JSON.parse(res)
|
51
53
|
if res['outcome'] != 'SUCCESS'
|
52
54
|
msg = "Keyboard enter failed failed because: #{res['reason']}\n#{res['details']}"
|
@@ -68,10 +70,10 @@ module Calabash
|
|
68
70
|
end
|
69
71
|
|
70
72
|
def done
|
71
|
-
if
|
73
|
+
if uia?
|
72
74
|
uia_type_string '\n'
|
73
75
|
else
|
74
|
-
keyboard_enter_char
|
76
|
+
keyboard_enter_char 'Return'
|
75
77
|
end
|
76
78
|
|
77
79
|
end
|
@@ -122,13 +124,21 @@ module Calabash
|
|
122
124
|
end
|
123
125
|
|
124
126
|
def await_keyboard
|
125
|
-
|
126
|
-
|
127
|
+
#deprecated inconsistent wait naming
|
128
|
+
# use wait_for_keyboard
|
129
|
+
wait_for_keyboard
|
130
|
+
end
|
131
|
+
|
132
|
+
#noinspection RubyLiteralArrayInspection
|
133
|
+
def wait_for_keyboard
|
134
|
+
wait_for_elements_exist(["view:'UIKBKeyplaneView'"], :timeout_message => 'No visible keyboard')
|
135
|
+
sleep(0.5)
|
127
136
|
end
|
128
137
|
|
129
138
|
def keyboard_enter_text(text)
|
130
|
-
|
131
|
-
|
139
|
+
wait_for_keyboard if element_does_not_exist("view:'UIKBKeyplaneView'")
|
140
|
+
|
141
|
+
if uia?
|
132
142
|
uia_type_string(text)
|
133
143
|
else
|
134
144
|
text.each_char do |ch|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'calabash-cucumber/launch/simulator_helper'
|
2
2
|
require 'sim_launcher'
|
3
3
|
require 'calabash-cucumber/device'
|
4
|
+
require 'calabash-cucumber/actions/instruments_actions'
|
5
|
+
require 'calabash-cucumber/actions/playback_actions'
|
4
6
|
require 'run_loop'
|
5
7
|
require 'cfpropertylist'
|
6
8
|
|
@@ -10,6 +12,7 @@ class Calabash::Cucumber::Launcher
|
|
10
12
|
|
11
13
|
attr_accessor :run_loop
|
12
14
|
attr_accessor :device
|
15
|
+
attr_accessor :actions
|
13
16
|
attr_accessor :launch_args
|
14
17
|
|
15
18
|
@@launcher = nil
|
@@ -29,6 +32,12 @@ class Calabash::Cucumber::Launcher
|
|
29
32
|
class CalabashLauncherTimeoutErr < Timeout::Error
|
30
33
|
end
|
31
34
|
|
35
|
+
|
36
|
+
def actions
|
37
|
+
attach if @actions.nil?
|
38
|
+
@actions
|
39
|
+
end
|
40
|
+
|
32
41
|
def self.attach
|
33
42
|
l = launcher
|
34
43
|
return l if l && l.active?
|
@@ -36,15 +45,32 @@ class Calabash::Cucumber::Launcher
|
|
36
45
|
|
37
46
|
end
|
38
47
|
|
39
|
-
def attach
|
48
|
+
def attach(max_retry=1, timeout=10)
|
40
49
|
pids_str = `ps x -o pid,command | grep -v grep | grep "instruments" | awk '{printf "%s,", $1}'`
|
41
50
|
pids = pids_str.split(',').map { |pid| pid.to_i }
|
42
51
|
pid = pids.first
|
43
52
|
rl = {}
|
44
|
-
|
53
|
+
if pid
|
54
|
+
rl[:pid] = pid
|
55
|
+
self.actions= Calabash::Cucumber::InstrumentsActions.new
|
56
|
+
else
|
57
|
+
self.actions= Calabash::Cucumber::PlaybackActions.new
|
58
|
+
end
|
45
59
|
|
46
60
|
self.run_loop= rl
|
47
|
-
|
61
|
+
|
62
|
+
ensure_connectivity(max_retry, timeout)
|
63
|
+
|
64
|
+
major = self.device.ios_major_version
|
65
|
+
if major.to_i >= 7 && self.actions.is_a?(Calabash::Cucumber::PlaybackActions)
|
66
|
+
puts "\n\n WARNING \n\n"
|
67
|
+
puts 'Warning Trying to connect to simulator that was not launched by Calabash/instruments.'
|
68
|
+
puts 'To fix this you must let Calabash or instruments launch the app'
|
69
|
+
puts 'Continuing... query et al will work.'
|
70
|
+
puts "\n\n WARNING \n\n"
|
71
|
+
puts "Please read: https://github.com/calabash/calabash-ios/wiki/A0-UIAutomation---instruments-problems"
|
72
|
+
end
|
73
|
+
|
48
74
|
|
49
75
|
self
|
50
76
|
end
|
@@ -52,7 +78,7 @@ class Calabash::Cucumber::Launcher
|
|
52
78
|
def self.instruments?
|
53
79
|
l = launcher_if_used
|
54
80
|
return false unless l
|
55
|
-
l.
|
81
|
+
l.instruments?
|
56
82
|
end
|
57
83
|
|
58
84
|
def self.launcher
|
@@ -67,6 +93,8 @@ class Calabash::Cucumber::Launcher
|
|
67
93
|
@@launcher = self
|
68
94
|
end
|
69
95
|
|
96
|
+
|
97
|
+
|
70
98
|
def ios_major_version
|
71
99
|
return nil if device.nil? or device.ios_version.nil?
|
72
100
|
device.ios_major_version
|
@@ -280,10 +308,12 @@ class Calabash::Cucumber::Launcher
|
|
280
308
|
|
281
309
|
if run_with_instruments?(args)
|
282
310
|
self.run_loop = new_run_loop(args)
|
311
|
+
self.actions= Calabash::Cucumber::InstrumentsActions.new
|
283
312
|
else
|
284
313
|
# run with sim launcher
|
285
314
|
sdk = sdk_version || SimLauncher::SdkDetector.new().available_sdk_versions.reverse.find { |x| !x.start_with?('7') }
|
286
315
|
path = Calabash::Cucumber::SimulatorHelper.app_bundle_or_raise(app_path)
|
316
|
+
self.actions= Calabash::Cucumber::PlaybackActions.new
|
287
317
|
Calabash::Cucumber::SimulatorHelper.relaunch(path, sdk, args[:device].to_s, args)
|
288
318
|
end
|
289
319
|
self.launch_args = args
|
@@ -353,10 +383,10 @@ class Calabash::Cucumber::Launcher
|
|
353
383
|
raise StartError.new(last_err)
|
354
384
|
end
|
355
385
|
|
356
|
-
def ensure_connectivity
|
386
|
+
def ensure_connectivity(max_retry=10, timeout=30)
|
357
387
|
begin
|
358
|
-
max_retry_count = (ENV['MAX_CONNECT_RETRY'] ||
|
359
|
-
timeout = (ENV['CONNECT_TIMEOUT'] ||
|
388
|
+
max_retry_count = (ENV['MAX_CONNECT_RETRY'] || max_retry).to_i
|
389
|
+
timeout = (ENV['CONNECT_TIMEOUT'] || timeout).to_i
|
360
390
|
retry_count = 0
|
361
391
|
connected = false
|
362
392
|
if ENV['CALABASH_FULL_CONSOLE_OUTPUT'] == '1'
|
@@ -414,7 +444,7 @@ class Calabash::Cucumber::Launcher
|
|
414
444
|
end
|
415
445
|
|
416
446
|
def stop
|
417
|
-
RunLoop.stop(run_loop)
|
447
|
+
RunLoop.stop(run_loop) if run_loop && run_loop[:pid]
|
418
448
|
end
|
419
449
|
|
420
450
|
def calabash_notify(world)
|
@@ -486,6 +516,10 @@ class Calabash::Cucumber::Launcher
|
|
486
516
|
not run_loop.nil?
|
487
517
|
end
|
488
518
|
|
519
|
+
def instruments?
|
520
|
+
!!(active? && run_loop[:pid])
|
521
|
+
end
|
522
|
+
|
489
523
|
def inspect
|
490
524
|
msg = ["#{self.class}: Launch Method #{launch_args && launch_args[:launch_method]}"]
|
491
525
|
if run_with_instruments?(self.launch_args) && self.run_loop
|