calabash-cucumber 0.10.0.pre1 → 0.10.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/features/step_definitions/calabash_steps.rb +1 -1
  3. data/lib/calabash-cucumber/actions/instruments_actions.rb +15 -4
  4. data/lib/calabash-cucumber/actions/playback_actions.rb +12 -3
  5. data/lib/calabash-cucumber/connection.rb +3 -0
  6. data/lib/calabash-cucumber/connection_helpers.rb +4 -0
  7. data/lib/calabash-cucumber/core.rb +637 -83
  8. data/lib/calabash-cucumber/date_picker.rb +148 -29
  9. data/lib/calabash-cucumber/device.rb +160 -3
  10. data/lib/calabash-cucumber/environment_helpers.rb +91 -46
  11. data/lib/calabash-cucumber/failure_helpers.rb +40 -0
  12. data/lib/calabash-cucumber/http_helpers.rb +9 -2
  13. data/lib/calabash-cucumber/ibase.rb +136 -17
  14. data/lib/calabash-cucumber/ios7_operations.rb +13 -9
  15. data/lib/calabash-cucumber/ipad_1x_2x.rb +103 -48
  16. data/lib/calabash-cucumber/keyboard_helpers.rb +253 -144
  17. data/lib/calabash-cucumber/keychain_helpers.rb +46 -32
  18. data/lib/calabash-cucumber/launch/simulator_helper.rb +13 -12
  19. data/lib/calabash-cucumber/launch/simulator_launcher.rb +111 -78
  20. data/lib/calabash-cucumber/launcher.rb +265 -25
  21. data/lib/calabash-cucumber/map.rb +24 -22
  22. data/lib/calabash-cucumber/operations.rb +4 -160
  23. data/lib/calabash-cucumber/playback_helpers.rb +26 -0
  24. data/lib/calabash-cucumber/query_helpers.rb +12 -0
  25. data/lib/calabash-cucumber/rotation_helpers.rb +64 -8
  26. data/lib/calabash-cucumber/status_bar_helpers.rb +40 -3
  27. data/lib/calabash-cucumber/tests_helpers.rb +43 -14
  28. data/lib/calabash-cucumber/uia.rb +93 -9
  29. data/lib/calabash-cucumber/utils/logging.rb +30 -16
  30. data/lib/calabash-cucumber/utils/plist_buddy.rb +18 -19
  31. data/lib/calabash-cucumber/utils/simulator_accessibility.rb +41 -30
  32. data/lib/calabash-cucumber/utils/xctools.rb +31 -21
  33. data/lib/calabash-cucumber/version.rb +98 -2
  34. data/lib/calabash-cucumber/wait_helpers.rb +257 -77
  35. data/staticlib/calabash.framework.zip +0 -0
  36. metadata +64 -231
  37. data/.gitignore +0 -17
  38. data/CHANGES.txt +0 -1
  39. data/Gemfile +0 -4
  40. data/Rakefile +0 -72
  41. data/calabash-cucumber.gemspec +0 -36
  42. data/epl-v10.html +0 -261
  43. data/lib/calabash-cucumber/resources/cell_swipe_ios4_ipad.base64 +0 -51
  44. data/lib/calabash-cucumber/resources/cell_swipe_ios4_iphone.base64 +0 -51
  45. data/lib/calabash-cucumber/resources/cell_swipe_ios5_ipad.base64 +0 -74
  46. data/lib/calabash-cucumber/resources/cell_swipe_ios5_iphone.base64 +0 -74
  47. data/lib/calabash-cucumber/resources/double_tap_ios5_ipad.base64 +0 -15
  48. data/lib/calabash-cucumber/resources/double_tap_ios5_iphone.base64 +0 -15
  49. data/lib/calabash-cucumber/resources/double_tap_ios6_ipad.base64 +0 -22
  50. data/lib/calabash-cucumber/resources/double_tap_ios6_iphone.base64 +0 -22
  51. data/lib/calabash-cucumber/resources/pan_ios5_ipad.base64 +0 -199
  52. data/lib/calabash-cucumber/resources/pan_ios5_iphone.base64 +0 -199
  53. data/lib/calabash-cucumber/resources/pan_ios6_ipad.base64 +0 -206
  54. data/lib/calabash-cucumber/resources/pan_ios6_iphone.base64 +0 -206
  55. data/lib/calabash-cucumber/resources/pinch_in_ios4_ipad.base64 +0 -104
  56. data/lib/calabash-cucumber/resources/pinch_in_ios4_iphone.base64 +0 -104
  57. data/lib/calabash-cucumber/resources/pinch_in_ios5_ipad.base64 +0 -144
  58. data/lib/calabash-cucumber/resources/pinch_in_ios5_iphone.base64 +0 -144
  59. data/lib/calabash-cucumber/resources/pinch_in_ios6_ipad.base64 +0 -70
  60. data/lib/calabash-cucumber/resources/pinch_in_ios6_iphone.base64 +0 -70
  61. data/lib/calabash-cucumber/resources/pinch_out_ios5_ipad.base64 +0 -207
  62. data/lib/calabash-cucumber/resources/pinch_out_ios5_iphone.base64 +0 -207
  63. data/lib/calabash-cucumber/resources/pinch_out_ios6_ipad.base64 +0 -96
  64. data/lib/calabash-cucumber/resources/pinch_out_ios6_iphone.base64 +0 -96
  65. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios4_ipad.base64 +0 -2
  66. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios4_iphone.base64 +0 -2
  67. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios5_ipad.base64 +0 -2
  68. data/lib/calabash-cucumber/resources/rotate_left_home_down_ios5_iphone.base64 +0 -2
  69. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios4_ipad.base64 +0 -2
  70. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios4_iphone.base64 +0 -2
  71. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios5_ipad.base64 +0 -2
  72. data/lib/calabash-cucumber/resources/rotate_left_home_left_ios5_iphone.base64 +0 -2
  73. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios4_ipad.base64 +0 -2
  74. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios4_iphone.base64 +0 -2
  75. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios5_ipad.base64 +0 -2
  76. data/lib/calabash-cucumber/resources/rotate_left_home_right_ios5_iphone.base64 +0 -2
  77. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios4_ipad.base64 +0 -2
  78. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios4_iphone.base64 +0 -2
  79. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios5_ipad.base64 +0 -2
  80. data/lib/calabash-cucumber/resources/rotate_left_home_up_ios5_iphone.base64 +0 -2
  81. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios4_ipad.base64 +0 -2
  82. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios4_iphone.base64 +0 -2
  83. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios5_ipad.base64 +0 -2
  84. data/lib/calabash-cucumber/resources/rotate_right_home_down_ios5_iphone.base64 +0 -2
  85. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios4_ipad.base64 +0 -2
  86. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios4_iphone.base64 +0 -2
  87. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios5_ipad.base64 +0 -2
  88. data/lib/calabash-cucumber/resources/rotate_right_home_left_ios5_iphone.base64 +0 -2
  89. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios4_ipad.base64 +0 -2
  90. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios4_iphone.base64 +0 -2
  91. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios5_ipad.base64 +0 -2
  92. data/lib/calabash-cucumber/resources/rotate_right_home_right_ios5_iphone.base64 +0 -2
  93. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios4_ipad.base64 +0 -2
  94. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios4_iphone.base64 +0 -2
  95. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios5_ipad.base64 +0 -2
  96. data/lib/calabash-cucumber/resources/rotate_right_home_up_ios5_iphone.base64 +0 -2
  97. data/lib/calabash-cucumber/resources/swipe_down_ios5_ipad.base64 +0 -18
  98. data/lib/calabash-cucumber/resources/swipe_down_ios5_iphone.base64 +0 -31
  99. data/lib/calabash-cucumber/resources/swipe_down_ios6_ipad.base64 +0 -25
  100. data/lib/calabash-cucumber/resources/swipe_down_ios6_iphone.base64 +0 -25
  101. data/lib/calabash-cucumber/resources/swipe_left_hard_ios4_ipad.base64 +0 -15
  102. data/lib/calabash-cucumber/resources/swipe_left_hard_ios4_iphone.base64 +0 -15
  103. data/lib/calabash-cucumber/resources/swipe_left_ios4_ipad.base64 +0 -18
  104. data/lib/calabash-cucumber/resources/swipe_left_ios4_iphone.base64 +0 -18
  105. data/lib/calabash-cucumber/resources/swipe_left_ios5_ipad.base64 +0 -17
  106. data/lib/calabash-cucumber/resources/swipe_left_ios5_iphone.base64 +0 -34
  107. data/lib/calabash-cucumber/resources/swipe_left_ios6_ipad.base64 +0 -28
  108. data/lib/calabash-cucumber/resources/swipe_left_ios6_iphone.base64 +0 -28
  109. data/lib/calabash-cucumber/resources/swipe_right_hard_ios4_ipad.base64 +0 -17
  110. data/lib/calabash-cucumber/resources/swipe_right_hard_ios4_iphone.base64 +0 -17
  111. data/lib/calabash-cucumber/resources/swipe_right_ios4_ipad.base64 +0 -13
  112. data/lib/calabash-cucumber/resources/swipe_right_ios4_iphone.base64 +0 -13
  113. data/lib/calabash-cucumber/resources/swipe_right_ios5_ipad.base64 +0 -17
  114. data/lib/calabash-cucumber/resources/swipe_right_ios5_iphone.base64 +0 -17
  115. data/lib/calabash-cucumber/resources/swipe_right_ios6_ipad.base64 +0 -25
  116. data/lib/calabash-cucumber/resources/swipe_right_ios6_iphone.base64 +0 -25
  117. data/lib/calabash-cucumber/resources/swipe_up_ios5_ipad.base64 +0 -34
  118. data/lib/calabash-cucumber/resources/swipe_up_ios5_iphone.base64 +0 -28
  119. data/lib/calabash-cucumber/resources/swipe_up_ios6_ipad.base64 +0 -25
  120. data/lib/calabash-cucumber/resources/swipe_up_ios6_iphone.base64 +0 -25
  121. data/lib/calabash-cucumber/resources/touch_done_ios4_ipad.base64 +0 -7
  122. data/lib/calabash-cucumber/resources/touch_done_ios4_iphone.base64 +0 -9
  123. data/lib/calabash-cucumber/resources/touch_done_ios5_ipad.base64 +0 -7
  124. data/lib/calabash-cucumber/resources/touch_done_ios5_iphone.base64 +0 -9
  125. data/lib/calabash-cucumber/resources/touch_hold_ios5_ipad.base64 +0 -9
  126. data/lib/calabash-cucumber/resources/touch_hold_ios5_iphone.base64 +0 -9
  127. data/lib/calabash-cucumber/resources/touch_hold_ios6_ipad.base64 +0 -9
  128. data/lib/calabash-cucumber/resources/touch_hold_ios6_iphone.base64 +0 -9
  129. data/lib/calabash-cucumber/resources/touch_ios4_ipad.base64 +0 -9
  130. data/lib/calabash-cucumber/resources/touch_ios4_iphone.base64 +0 -9
  131. data/lib/calabash-cucumber/resources/touch_ios5_ipad.base64 +0 -9
  132. data/lib/calabash-cucumber/resources/touch_ios5_iphone.base64 +0 -9
  133. data/lib/calabash-cucumber/resources/touch_ios7_ipad.base64 +0 -9
  134. data/lib/calabash-cucumber/resources/touch_ios7_iphone.base64 +0 -9
  135. data/lib/calabash-cucumber/resources/wheel_down_ios4_ipad.base64 +0 -159
  136. data/lib/calabash-cucumber/resources/wheel_down_ios4_iphone.base64 +0 -159
  137. data/lib/calabash-cucumber/resources/wheel_down_ios5_ipad.base64 +0 -156
  138. data/lib/calabash-cucumber/resources/wheel_down_ios5_iphone.base64 +0 -156
  139. data/lib/calabash-cucumber/resources/wheel_up_ios4_ipad.base64 +0 -166
  140. data/lib/calabash-cucumber/resources/wheel_up_ios4_iphone.base64 +0 -166
  141. data/lib/calabash-cucumber/resources/wheel_up_ios5_ipad.base64 +0 -156
  142. data/lib/calabash-cucumber/resources/wheel_up_ios5_iphone.base64 +0 -156
  143. data/scripts/EmptyAppHack.app/Default-568h@2x.png +0 -0
  144. data/scripts/EmptyAppHack.app/Default.png +0 -0
  145. data/scripts/EmptyAppHack.app/Default@2x.png +0 -0
  146. data/scripts/EmptyAppHack.app/EmptyAppHack +0 -0
  147. data/scripts/EmptyAppHack.app/Info.plist +0 -0
  148. data/scripts/EmptyAppHack.app/PkgInfo +0 -1
  149. data/scripts/EmptyAppHack.app/en.lproj/InfoPlist.strings +0 -0
  150. data/scripts/com.example.plist +0 -0
  151. data/scripts/data/.GlobalPreferences.plist +0 -0
  152. data/scripts/reset_simulator.scpt +0 -0
  153. data/spec/bin/calabash_ios_sim_spec.rb +0 -24
  154. data/spec/launcher_spec.rb +0 -166
  155. data/spec/logging_spec.rb +0 -38
  156. data/spec/plist_buddy_spec.rb +0 -99
  157. data/spec/resources/enable-accessibility/6.1/.gitkeep +0 -0
  158. data/spec/resources/enable-accessibility/7.0.3-64/.gitkeep +0 -0
  159. data/spec/resources/enable-accessibility/7.0.3/.gitkeep +0 -0
  160. data/spec/resources/enable-accessibility/7.1-64/.gitkeep +0 -0
  161. data/spec/resources/enable-accessibility/7.1/.gitkeep +0 -0
  162. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Default-568h@2x.png +0 -0
  163. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist +0 -0
  164. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal +0 -0
  165. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/PkgInfo +0 -1
  166. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/InfoPlist.strings +0 -0
  167. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController.nib +0 -0
  168. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController~ipad.nib +0 -0
  169. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController.nib +0 -0
  170. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController~ipad.nib +0 -0
  171. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController.nib +0 -0
  172. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController~ipad.nib +0 -0
  173. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController.nib +0 -0
  174. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController~ipad.nib +0 -0
  175. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first.png +0 -0
  176. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first@2x.png +0 -0
  177. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second.png +0 -0
  178. data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second@2x.png +0 -0
  179. data/spec/resources/plist_buddy/com.example.plist +0 -0
  180. data/spec/resources/plist_buddy/com.testing.plist +0 -18
  181. data/spec/simulator_accessibility_spec.rb +0 -206
  182. data/spec/spec_helper.rb +0 -31
  183. data/spec/version_spec.rb +0 -13
  184. data/spec/xctools_spec.rb +0 -58
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e7927ef644a1b54f7448642b9d06207c30d2781
4
- data.tar.gz: 46d85fece887a5df72522a76597503d5ae1c46da
3
+ metadata.gz: 58c9160b3ab46994846c1a6ba017d7ad33a552d3
4
+ data.tar.gz: bb4bf0b81e4d8b6723ba8827fad48384202b2394
5
5
  SHA512:
6
- metadata.gz: fcf04088f7b3eb9150167371e768f45531c72ff3d5f459be76f3f57a07c18590d83d82adc1b6f274b20d2324bb92797f1c1c761bc991356ba4fb977e9d4c8d96
7
- data.tar.gz: 51225cb4a75b0dbeb6f23f56dc579b1ea55a77c36ccbbb1c050d3296eedfb185dae4db587978c13cf7c1d0f55fc1639c212d0d81f1a1e591a6b6585c5b82d7c6
6
+ metadata.gz: b3d7061cf22b4bdef135a9abc4cf7f69a2356616893940e7d03e6064c7f1ea6f4e83ee2ff73d80a7fdf9103dc76780631069ae178ffad9676400dbe8e4647e22
7
+ data.tar.gz: a0b47ef74ffed7850725ae2047c9e0f2189a75e538a1064759035b7e045401844141b7dd8994d1c4fce22df72e118ddb5fa3419f7f2b7aa2c19469357acacbff
@@ -17,7 +17,7 @@ Then /^I (?:press|touch) "([^\"]*)"$/ do |name|
17
17
  sleep(STEP_PAUSE)
18
18
  end
19
19
 
20
- Then /^I (?:press|touch) (\d+)% right and (\d+)% down from "([^\"]*)" $/ do |x,y,name|
20
+ Then /^I (?:press|touch) (\d+)% right and (\d+)% down from "([^\"]*)"$/ do |x,y,name|
21
21
  raise "This step is not yet implemented on iOS"
22
22
  end
23
23
 
@@ -3,28 +3,34 @@ require 'calabash-cucumber/connection_helpers'
3
3
  require 'calabash-cucumber/query_helpers'
4
4
  require 'calabash-cucumber/map'
5
5
 
6
+ # @!visibility private
6
7
  class Calabash::Cucumber::InstrumentsActions
7
8
  include Calabash::Cucumber::UIA
8
9
  include Calabash::Cucumber::ConnectionHelpers
9
10
  include Calabash::Cucumber::QueryHelpers
10
11
  include Calabash::Cucumber::Map
11
12
 
13
+ # @!visibility private
12
14
  def touch(options)
13
15
  query_action(options, :uia_tap_offset)
14
16
  end
15
17
 
18
+ # @!visibility private
16
19
  def wait_tap(options)
17
20
  uia_wait_tap(options[:query], options)
18
21
  end
19
22
 
23
+ # @!visibility private
20
24
  def double_tap(options)
21
25
  query_action(options, :uia_double_tap_offset)
22
26
  end
23
27
 
28
+ # @!visibility private
24
29
  def two_finger_tap(options)
25
30
  query_action(options, :uia_two_finger_tap_offset)
26
31
  end
27
32
 
33
+ # @!visibility private
28
34
  def flick(options)
29
35
  query_action(options) do |offset|
30
36
  delta = {:offset => options[:delta] || {}}
@@ -32,28 +38,30 @@ class Calabash::Cucumber::InstrumentsActions
32
38
  end
33
39
  end
34
40
 
35
-
41
+ # @!visibility private
36
42
  def touch_hold(options)
37
43
  query_action(options) do |offset|
38
- duration = options[:duration] || 4
44
+ duration = options[:duration] || 3
39
45
  uia_touch_hold_offset(duration, offset)
40
46
  end
41
47
  end
42
48
 
49
+ # @!visibility private
43
50
  def swipe(dir, options={})
44
51
  options = options.merge(:direction => dir)
45
52
  query_action(options, :uia_swipe_offset, options)
46
53
  end
47
54
 
55
+ # @!visibility private
48
56
  def pan(from, to, options={})
49
57
  query_action(:query => from) do |from_offset|
50
58
  query_action(:query => to) do |to_offset|
51
59
  uia_pan_offset(from_offset, to_offset, options)
52
60
  end
53
61
  end
54
-
55
62
  end
56
63
 
64
+ # @!visibility private
57
65
  def pinch(in_out, options)
58
66
  query_action(options) do |offset|
59
67
  options[:duration] = options[:duration] || 0.5
@@ -61,12 +69,14 @@ class Calabash::Cucumber::InstrumentsActions
61
69
  end
62
70
  end
63
71
 
72
+ # @!visibility private
64
73
  def send_app_to_background(secs)
65
74
  uia_send_app_to_background(secs)
66
75
  end
67
76
 
68
77
  private
69
78
 
79
+ # @!visibility private
70
80
  # Data interface
71
81
  # options[:query] or options[:offset]
72
82
  def query_action(options, action=nil, *args, &block)
@@ -93,6 +103,7 @@ class Calabash::Cucumber::InstrumentsActions
93
103
  end
94
104
  end
95
105
 
106
+ # @!visibility private
96
107
  def find_and_normalize(ui_query)
97
108
  raw_result = raw_map(ui_query, :query)
98
109
  orientation = raw_result['status_bar_orientation']
@@ -106,6 +117,7 @@ class Calabash::Cucumber::InstrumentsActions
106
117
  res
107
118
  end
108
119
 
120
+ # @!visibility private
109
121
  def normalize_rect_for_orientation!(orientation, rect)
110
122
  orientation = orientation.to_sym
111
123
  launcher = Calabash::Cucumber::Launcher.launcher
@@ -129,5 +141,4 @@ class Calabash::Cucumber::InstrumentsActions
129
141
  end
130
142
  end
131
143
 
132
-
133
144
  end
@@ -2,37 +2,43 @@ require 'calabash-cucumber/playback_helpers'
2
2
  require 'calabash-cucumber/connection_helpers'
3
3
  require 'calabash-cucumber/query_helpers'
4
4
 
5
-
5
+ # @!visibility private
6
6
  class Calabash::Cucumber::PlaybackActions
7
7
  include Calabash::Cucumber::PlaybackHelpers
8
8
  include Calabash::Cucumber::ConnectionHelpers
9
9
  include Calabash::Cucumber::QueryHelpers
10
10
 
11
-
11
+ # @!visibility private
12
12
  def touch(options)
13
13
  playback('touch', options)
14
14
  end
15
15
 
16
+ # @!visibility private
16
17
  def wait_tap(options)
17
18
  touch(options)
18
19
  end
19
20
 
21
+ # @!visibility private
20
22
  def double_tap(options)
21
23
  playback('double_tap', options)
22
24
  end
23
25
 
26
+ # @!visibility private
24
27
  def two_finger_tap(*args)
25
28
  raise error_message('two_finger_tap')
26
29
  end
27
30
 
31
+ # @!visibility private
28
32
  def flick(*args)
29
33
  raise error_message('flick')
30
34
  end
31
35
 
36
+ # @!visibility private
32
37
  def touch_hold(options)
33
38
  playback('touch_hold', options)
34
39
  end
35
40
 
41
+ # @!visibility private
36
42
  def swipe(dir, options={})
37
43
  current_orientation = options[:status_bar_orientation].to_sym
38
44
  if current_orientation == :left
@@ -81,10 +87,12 @@ class Calabash::Cucumber::PlaybackActions
81
87
 
82
88
  end
83
89
 
90
+ # @!visibility private
84
91
  def pan(from,to,options={})
85
92
  interpolate 'pan', options.merge(:start => from, :end => to)
86
93
  end
87
94
 
95
+ # @!visibility private
88
96
  def pinch(in_out,options)
89
97
  file = "pinch_in"
90
98
  if in_out==:out
@@ -93,12 +101,13 @@ class Calabash::Cucumber::PlaybackActions
93
101
  playback(file, options)
94
102
  end
95
103
 
104
+ # @!visibility private
96
105
  def send_app_to_background(secs)
97
106
  raise 'Not implemented when running without instruments / UIA'
98
107
  end
99
108
 
100
-
101
109
  private
110
+ # @!visibility private
102
111
  def error_message(gesture)
103
112
  "Gesture: '#{gesture}' not supported unless running with instruments."
104
113
  end
@@ -3,10 +3,13 @@ require 'calabash-cucumber/http_helpers'
3
3
 
4
4
  module Calabash
5
5
  module Cucumber
6
+
7
+ # @!visibility private
6
8
  class Connection
7
9
  include Singleton
8
10
  include HTTPHelpers
9
11
 
12
+ # @!visibility private
10
13
  def client
11
14
  @http
12
15
  end
@@ -2,12 +2,16 @@ require 'calabash-cucumber/connection'
2
2
 
3
3
  module Calabash
4
4
  module Cucumber
5
+
6
+ # @!visibility private
5
7
  module ConnectionHelpers
6
8
 
9
+ # @!visibility private
7
10
  def http(*args)
8
11
  connection.http(*args)
9
12
  end
10
13
 
14
+ # @!visibility private
11
15
  def connection
12
16
  Calabash::Cucumber::Connection.instance
13
17
  end
@@ -21,6 +21,8 @@ require 'calabash-cucumber/launch/simulator_helper'
21
21
 
22
22
  module Calabash
23
23
  module Cucumber
24
+
25
+ # A collection of methods that provide the core calabash behaviors.
24
26
  module Core
25
27
 
26
28
  include Calabash::Cucumber::Logging
@@ -34,6 +36,10 @@ module Calabash
34
36
  include Calabash::Cucumber::RotationHelpers
35
37
  include Calabash::Cucumber::PlaybackHelpers
36
38
 
39
+ # @!visibility private
40
+ # @deprecated Use Cucumber's step method (avoid this: using step is not considered best practice).
41
+ # Used in older cucumber versions that didn't have the `step` method.
42
+ # Shouldn't be used anymore.
37
43
  def macro(txt)
38
44
  if self.respond_to? :step
39
45
  step(txt)
@@ -42,37 +48,106 @@ module Calabash
42
48
  end
43
49
  end
44
50
 
51
+ # The core method for querying into the current visible view
52
+ # of the app under test. The query method takes as first parameter
53
+ # a String `:uiquery`. This string must follow the query syntax
54
+ # described in:
55
+ # {http://developer.xamarin.com/guides/testcloud/calabash/calabash-query-syntax/ Query Syntax}.
56
+ #
57
+ # Optionally `query` takes a variable number of "invocation" arguments
58
+ # (`args` below). # If called with an empty list of `*args`, `query`
59
+ # will find the views specified by `uiquery` and return a serialized view
60
+ # (see Examples below).
61
+ #
62
+ # If `*args` are given, then they should describe a valid selector invocation
63
+ # on the queried views. For example `query('UILabel', :text)` would perform
64
+ # the `:text` selector on all visible `UILabel` objects and return those as
65
+ # an Array of Strings.
66
+ #
67
+ # The `query` method provide a powerful mechanism for `querying` app view state
68
+ # and can be used to reflectively call arbitrary methods on objects reachable
69
+ # from the view. For a full specification of `*args` see
70
+ # {http://developer.xamarin.com/guides/testcloud/calabash/calabash-query-syntax/ Query Syntax}.
71
+ #
72
+ # @example Basic view query
73
+ # irb(main):009:0> query("UITabBarButton index:0")
74
+ # [
75
+ # [0] {
76
+ # "class" => "UITabBarButton",
77
+ # "id" => nil,
78
+ # "rect" => {
79
+ # "center_x" => 40,
80
+ # "y" => 520,
81
+ # "width" => 76,
82
+ # "x" => 2,
83
+ # "center_y" => 544,
84
+ # "height" => 48
85
+ # },
86
+ # "frame" => {
87
+ # "y" => 1,
88
+ # "width" => 76,
89
+ # "x" => 2,
90
+ # "height" => 48
91
+ # },
92
+ # "label" => "Reader",
93
+ # "description" => "<UITabBarButton: 0xdabb510; frame = (2 1; 76 48); opaque = NO; layer = <CALayer: 0xdabd8e0>>"
94
+ # }
95
+ # ]
96
+ # @example Simple selector
97
+ # irb(main):010:0> query("UILabel", :text)
98
+ # [
99
+ # [0] "The Ugly Volvo",
100
+ # [1] "Why Having a Baby Reminds me of Garfield Minus Garfield",
101
+ # [2] "I love the site Garfield Minus Garfield. If you don’t know the site Garfield minus Garfield  it’s a website run by a guy named Dan Walsh who takes Garfield comic strips and digitally erases Garfield from them. more",
102
+ # [3] "Freshly Pressed",
103
+ # [4] "Reader",
104
+ # [5] "Notifications",
105
+ # [6] "Me"
106
+ # ]
107
+ # @param [String] uiquery the query to perform. Must follow the query syntax:
108
+ # {http://developer.xamarin.com/guides/testcloud/calabash/calabash-query-syntax/ Query Syntax}.
109
+ # @param [Array] args optional var-args list describing a chain of method selectors.
110
+ # Full details {http://developer.xamarin.com/guides/testcloud/calabash/calabash-query-syntax/ Query Syntax}.
45
111
  def query(uiquery, *args)
46
112
  map(uiquery, :query, *args)
47
113
  end
48
114
 
115
+ # Shorthand alias for `query`.
116
+ # @see #query
117
+ # @!visibility private
49
118
  def q(uiquery, *args)
50
119
  query(uiquery, *args)
51
120
  end
52
121
 
53
- # causes all views matched by the +query+ to briefly change colors making
122
+ # Causes all views matched by the `uiquery` to briefly change colors making
54
123
  # them visually identifiable.
55
124
  #
56
- # returns <tt>[]</tt> if no views are matched
57
- #
58
- # if there are matching views, returns an array of that contains the
59
- # result of calling the objc selector +description+ on each matching view.
125
+ # @param [String] uiquery a query specifying which objects to flash
126
+ # @param [Array] args argument is ignored and should be deprecated
127
+ # @return [Array] an array of that contains the result of calling the
128
+ # objc selector `description` on each matching view.
60
129
  #
61
- # NB: the +args+ argument is ignored and should be deprecated
62
130
  def flash(uiquery, *args)
63
131
  # todo deprecate the *args argument in the flash method
64
132
  # todo :flash operation should return views as JSON objects
65
133
  map(uiquery, :flash, *args).compact
66
134
  end
67
135
 
136
+ # Returns the version of the running calabash server.
137
+ # @return [String] version of the running calabash server.
68
138
  def server_version
69
139
  JSON.parse(http(:path => 'version'))
70
140
  end
71
141
 
142
+ # Returns the version of the loaded Calabash library.
143
+ # @see Calabash::Cucumber::VERSION
144
+ # @return [String] the version of the loaded Calabash library.
72
145
  def client_version
73
146
  Calabash::Cucumber::VERSION
74
147
  end
75
148
 
149
+ # Queries all views in view hierarchy, even if not visible.
150
+ # @deprecated use the 'all' or 'visible' modifier in query syntax
76
151
  def query_all(uiquery, *args)
77
152
  msg0 = "use the 'all' or 'visible' query language feature"
78
153
  msg1 = 'see: https://github.com/calabash/calabash-ios/wiki/05-Query-syntax'
@@ -81,28 +156,124 @@ module Calabash
81
156
  map("all #{uiquery}", :query, *args)
82
157
  end
83
158
 
159
+ # Performs the `tap` gesture on the (first) view that matches
160
+ # query `uiquery`. Note that `touch` assumes the view is visible and not animating.
161
+ # If the view is not visible `touch` will fail. If the view is animating
162
+ # `touch` will *silently* fail.
163
+ # By default, taps the center of the view.
164
+ # @see #wait_tap
165
+ # @see Calabash::Cucumber::Operations#tap_mark
166
+ # @see #tap_point
167
+ # @param {String} uiquery query describing view to tap. Note `nil` is allowed and is interpreted as
168
+ # `tap_point(options[:offset][:x],options[:offset][:y])`
169
+ # @param {Hash} options option for modifying the details of the touch
170
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
171
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
172
+ # @return {Array<Hash>} array containing the serialized version of the tapped view.
84
173
  def touch(uiquery, options={})
85
174
  query_action_with_options(:touch, uiquery, options)
86
175
  end
87
176
 
177
+ # Performs the `tap` gesture on an absolute coordinate.
178
+ # @see #wait_tap
179
+ # @see Calabash::Cucumber::Operations#tap_mark
180
+ # @see #touch
181
+ # @param {Numeric} x x-coordinate to tap
182
+ # @param {Numeric} y y-coordinate to tap
183
+ # @return {Boolean} `true`
184
+ def tap_point(x,y)
185
+ touch(nil, offset: {x:x, y:y})
186
+ end
187
+
188
+ # Performs the `tap` gesture on the (first) view that matches query `uiquery`.
189
+ #
190
+ # As opposed to `touch`, `wait_tap` is a high-level method that combines:
191
+ #
192
+ # 1. waiting for the view to appear,
193
+ # 2. waiting for animations to complete on the view (and it's parents) and
194
+ # 3. actually tapping the view.
195
+ #
196
+ # This removes the common boiler-plate trio: `wait_for_element_exists`,
197
+ # `wait_for_none_animating`, `touch`.
198
+ #
199
+ # By default, taps the center of the view.
200
+ # @see #touch
201
+ # @see #tap_point
202
+ # @param {String} uiquery query describing view to tap. Note `nil` is not allowed.
203
+ # @param {Hash} options option for modifying the details of the touch
204
+ # @option options {Hash} :offset (nil) optional offset to tap point. Offset has an `:x` and `:y` key
205
+ # the tap will be performed on the center of the view plus the offset.
206
+ # @option options {Hash} :timeout (30) maximum number of seconds to wait for the view to appear
207
+ # @option options {Hash} :frequency (0.2) polling frequency to for checking if the view is present (>= 0.1)
208
+ # @return {Array<Hash>} serialized version of the tapped view
88
209
  def wait_tap(uiquery, options={})
210
+ # noinspection RubyUnusedLocalVariable
89
211
  _uiquery, options = extract_query_and_options(uiquery, options)
90
212
  launcher.actions.wait_tap(options)
91
213
  end
92
214
 
93
- def t(uiquery, options={})
94
- wait_tap(uiquery, options)
95
- end
96
-
97
-
215
+ # Performs the "double tap" gesture on the (first) view that matches query `uiquery`.
216
+ #
217
+ # @note This assumes the view is visible and not animating.
218
+ #
219
+ # If the view is not visible it will fail with an error. If the view is animating
220
+ # it will *silently* fail.
221
+ #
222
+ # By default, taps the center of the view.
223
+ # @example
224
+ # double_tap "view marked:'Third'", offset:{x:100}
225
+ # @param {String} uiquery query describing view to touch.
226
+ # @param {Hash} options option for modifying the details of the touch
227
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
228
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
229
+ # @return {Array<Hash>} array containing the serialized version of the tapped view.
98
230
  def double_tap(uiquery, options={})
99
231
  query_action_with_options(:double_tap, uiquery, options)
100
232
  end
101
233
 
234
+ # Performs the "two-finger tap" gesture on the (first) view that matches
235
+ # query `uiquery`.
236
+ #
237
+ # @note This assumes the view is visible and not animating.
238
+ #
239
+ # If the view is not visible it will fail with an error. If the view is animating
240
+ # it will *silently* fail.
241
+ #
242
+ # By default, taps the center of the view.
243
+ #
244
+ # @example
245
+ # two_finger_tap "view marked:'Third'", offset:{x:100}
246
+ # @param {String} uiquery query describing view to touch.
247
+ # @param {Hash} options option for modifying the details of the touch.
248
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
249
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
250
+ # @return {Array<Hash>} array containing the serialized version of the tapped view.
102
251
  def two_finger_tap(uiquery,options={})
103
252
  query_action_with_options(:two_finger_tap, uiquery, options)
104
253
  end
105
254
 
255
+ # Performs the "flick" gesture on the (first) view that matches
256
+ # query `uiquery`.
257
+ #
258
+ # @note This assumes the view is visible and not animating.
259
+ #
260
+ # If the view is not visible it will fail with an error. If the view is animating
261
+ # it will *silently* fail.
262
+ #
263
+ # By default, the gesture starts at the center of the view and "flicks" according to `delta`.
264
+ #
265
+ # A flick is similar to a swipe.
266
+ #
267
+ # @example
268
+ # flick("MKMapView", {x:100,y:50})
269
+ # @param {String} uiquery query describing view to touch.
270
+ # @param {Hash} delta coordinate describing the direction to flick
271
+ # @param {Hash} options option for modifying the details of the touch.
272
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
273
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
274
+ # @option delta {Numeric} :x (0) optional. The force and direction of the flick on the `x`-axis
275
+ # @option delta {Numeric} :y (0) optional. The force and direction of the flick on the `y`-axis
276
+ # @return {Array<Hash>} array containing the serialized version of the touched view.
106
277
  def flick(uiquery, delta, options={})
107
278
  uiquery, options = extract_query_and_options(uiquery, options)
108
279
  options[:delta] = delta
@@ -113,10 +284,48 @@ module Calabash
113
284
  views_touched
114
285
  end
115
286
 
287
+ # Performs the "long press" or "touch and hold" gesture on the (first) view that matches
288
+ # query `uiquery`.
289
+ #
290
+ # @note This assumes the view is visible and not animating.
291
+ #
292
+ # If the view is not visible it will fail with an error. If the view is animating
293
+ # it will *silently* fail.
294
+ #
295
+ # By default, the gesture starts at the center of the view.
296
+ #
297
+ # @example
298
+ # touch_hold "webView css:'input'", duration:10, offset:{x: -40}
299
+ # @param {String} uiquery query describing view to touch.
300
+ # @param {Hash} options option for modifying the details of the touch.
301
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
302
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
303
+ # @option options {Numeric} :duration (3) duration of the 'hold'.
304
+ # @return {Array<Hash>} array containing the serialized version of the touched view.
116
305
  def touch_hold(uiquery, options={})
117
306
  query_action_with_options(:touch_hold, uiquery, options)
118
307
  end
119
308
 
309
+ # Performs a "swipe" gesture.
310
+ # By default, the gesture starts at the center of the screen.
311
+ #
312
+ # @todo `swipe` is an old style API which doesn't take a query as its
313
+ # first argument. We should migrate this.
314
+ #
315
+ # @note Due to a bug in Apple's UIAutomation, swipe is broken on certain
316
+ # views in the iOS Simulator. Swiping works on devices.
317
+ # {https://github.com/calabash/calabash-ios/issues/253}
318
+ #
319
+ # @example
320
+ # swipe :left
321
+ # @example
322
+ # swipe :down, offset:{x:10,y:50}, query:"MKMapView"
323
+ # @param {String} dir the direction to swipe (symbols can also be used).
324
+ # @param {Hash} options option for modifying the details of the touch.
325
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
326
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
327
+ # @option options {String} :query (nil) if specified, the swipe will be made relative to this query.
328
+ # @return {Array<Hash>,String} array containing the serialized version of the touched view if `options[:query]` is given.
120
329
  def swipe(dir, options={})
121
330
  unless uia_available?
122
331
  options = options.merge(:status_bar_orientation => status_bar_orientation)
@@ -124,14 +333,42 @@ module Calabash
124
333
  launcher.actions.swipe(dir.to_sym, options)
125
334
  end
126
335
 
336
+
337
+ # Performs the "pan" or "drag-n-drop" gesture on from the `from` parameter
338
+ # to the `to` parameter (both are queries).
339
+ # @example
340
+ # q1="* marked:'Cell 3' parent tableViewCell descendant tableViewCellReorderControl"
341
+ # q2="* marked:'Cell 6' parent tableViewCell descendant tableViewCellReorderControl"
342
+ # pan q1, q2, duration:4
343
+ # @param {String} from query describing view to start the gesture
344
+ # @param {String} to query describing view to end the gesture
345
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
346
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
347
+ # @option options {Numeric} :duration (1) duration of the 'pan'.
348
+ # @return {Array<Hash>} array containing the serialized version of the touched view.
127
349
  def pan(from, to, options={})
128
350
  launcher.actions.pan(from, to, options)
129
351
  end
130
352
 
353
+ # Performs a "pinch" gesture.
354
+ # By default, the gesture starts at the center of the screen.
355
+ # @todo `pinch` is an old style API which doesn't take a query as its first argument. We should migrate this.
356
+ # @example
357
+ # pinch :out
358
+ # @example
359
+ # pinch :in, query:"MKMapView", offset:{x:42}
360
+ # @param {String} in_out the direction to pinch ('in' or 'out') (symbols can also be used).
361
+ # @param {Hash} options option for modifying the details of the touch.
362
+ # @option options {Hash} :offset (nil) optional offset to touch point. Offset supports an `:x` and `:y` key
363
+ # and causes the touch to be offset with `(x,y)` relative to the center (`center + (offset[:x], offset[:y])`).
364
+ # @option options {String} :query (nil) if specified, the pinch will be made relative to this query.
365
+ # @return {Array<Hash>,String} array containing the serialized version of the touched view if `options[:query]` is given.
131
366
  def pinch(in_out, options={})
132
367
  launcher.actions.pinch(in_out.to_sym,options)
133
368
  end
134
369
 
370
+ # @!visibility private
371
+ # @deprecated
135
372
  def cell_swipe(options={})
136
373
  if uia_available?
137
374
  raise 'cell_swipe not supported with instruments, simply use swipe with a query that matches the cell'
@@ -139,6 +376,12 @@ module Calabash
139
376
  playback('cell_swipe', options)
140
377
  end
141
378
 
379
+ # Scroll a scroll view in a direction. By default scrolls half the frame size.
380
+ # @example
381
+ # scroll("UITableView", :down)
382
+ # @note this is implemented by calling the Obj-C `setContentOffset:animated:` method and can do things users cant.
383
+ #
384
+ # @param {String} uiquery query describing view scroll (should be UIScrollView or a web view).
142
385
  def scroll(uiquery, direction)
143
386
  views_touched=map(uiquery, :scroll, direction)
144
387
  msg = "could not find view to scroll: '#{uiquery}', args: #{direction}"
@@ -146,6 +389,14 @@ module Calabash
146
389
  views_touched
147
390
  end
148
391
 
392
+ # Scroll a table view to a row. Table view should have only one section.
393
+ # @see #scroll_to_cell
394
+ # @example
395
+ # scroll_to_row "UITableView", 2
396
+ # @note this is implemented by calling the Obj-C `scrollToRowAtIndexPath:atScrollPosition:animated:` method
397
+ # and can do things users cant.
398
+ #
399
+ # @param {String} uiquery query describing view scroll (should be UIScrollView or a web view).
149
400
  def scroll_to_row(uiquery, number)
150
401
  views_touched=map(uiquery, :scrollToRow, number)
151
402
  msg = "unable to scroll: '#{uiquery}' to: #{number}"
@@ -153,7 +404,22 @@ module Calabash
153
404
  views_touched
154
405
  end
155
406
 
156
- # todo for 1.0 version - scroll_to_cell should expose required arguments +section+ and +row+
407
+ # Scroll a table view to a section and row. Table view can have multiple sections.
408
+ #
409
+ # @todo should expose a non-option first argument query and required parameters `section`, `row`
410
+ #
411
+ # @see #scroll_to_row
412
+ # @example
413
+ # scroll_to_cell query:"UITableView", row:4, section:0, animate: false
414
+ # @note this is implemented by calling the Obj-C `scrollToRowAtIndexPath:atScrollPosition:animated:` method
415
+ # and can do things users cant.
416
+ #
417
+ # @param {Hash} options specifies details of the scroll
418
+ # @option options {String} :query ('tableView') query specifying which table view to scroll
419
+ # @option options {Fixnum} :section section to scroll to
420
+ # @option options {Fixnum} :row row to scroll to
421
+ # @option options {String} :scroll_position position to scroll to
422
+ # @option options {Boolean} :animated (true) animate or not
157
423
  def scroll_to_cell(options={:query => 'tableView',
158
424
  :row => 0,
159
425
  :section => 0,
@@ -181,34 +447,33 @@ module Calabash
181
447
  views_touched
182
448
  end
183
449
 
184
- # scrolls to +mark+ in a UITableView
185
- #
186
- # calls the +:scrollToRowWithMark+ server route
450
+ # Scrolls to a mark in a UITableView.
187
451
  #
188
- # scroll_to_row_with_mark(mark, {:scroll_position => :top}) #=> scroll to the top of the item with the given +mark+
189
- # scroll_to_row_with_mark(mark, {:scroll_position => :bottom}) #=> scroll to the bottom of the item with the given +mark+
452
+ # @example Scroll to the top of the item with the given mark.
453
+ # scroll_to_row_with_mark('settings', {:scroll_position => :top})
190
454
  #
191
- # allowed options
192
- # :query => a query string
193
- # default => 'tableView'
194
- # example => "tableView marked:'hit songs'"
455
+ # @example Scroll to the bottom of the item with the given mark.
456
+ # scroll_to_row_with_mark('about', {:scroll_position => :bottom})
195
457
  #
196
- # :scroll_position => the position to scroll to
197
- # default => :middle
198
- # allowed => {:top | :middle | :bottom}
458
+ # @param [String] mark an accessibility `{label | identifier}` or text in
459
+ # or on the row
460
+ # @param [Hash] options controls the query and and scroll behavior
199
461
  #
200
- # :animate => animate the scrolling
201
- # default => true
202
- # allowed => {true | false}
462
+ # @option options [String] :query ('tableView')
463
+ # the query that should be used to location the table
464
+ # @option options [Symbol] :scroll_position (:middle)
465
+ # the table position to scroll the row to - allowed values
466
+ # `{:middle | :top | :bottom}`
467
+ # @option options [Boolean] :animate (true)
468
+ # should the scrolling be animated
203
469
  #
204
- # raises an exception if the scroll cannot be performed.
205
- # * the +mark+ is nil
206
- # * the +:query+ finds no table view
207
- # * table view does not contain a cell with the given +mark+
208
- # * +:scroll_position+ is invalid
470
+ # @raise [RuntimeError] if the scroll cannot be performed
471
+ # @raise [RuntimeError] if the mark is nil
472
+ # @raise [RuntimeError] if the table query finds no table view
473
+ # @raise [RuntimeError] if the scroll position is invalid
209
474
  def scroll_to_row_with_mark(mark, options={:query => 'tableView',
210
- :scroll_position => :middle,
211
- :animate => true})
475
+ :scroll_position => :middle,
476
+ :animate => true})
212
477
  if mark.nil?
213
478
  screenshot_and_raise 'mark argument cannot be nil'
214
479
  end
@@ -231,36 +496,41 @@ module Calabash
231
496
  views_touched
232
497
  end
233
498
 
234
- # scrolls to +item+ in +section+ in a UICollectionView
499
+ # Scrolls to an item in a section of a UICollectionView.
500
+ #
501
+ # @note item and section are zero-indexed
235
502
  #
236
- # calls the +:collectionViewScroll+ server route
503
+ # @example Scroll to item 0 in section 2 to top.
504
+ # scroll_to_collection_view_item(0, 2, {:scroll_position => :top})
237
505
  #
238
- # +item+ and +section+ are zero-indexed
506
+ # @example Scroll to item 5 in section 0 to bottom.
507
+ # scroll_to_collection_view_item(5, 0, {:scroll_position => :bottom})
239
508
  #
240
- # scroll_to_collection_view_item(0, 2, {:scroll_position => :top}) #=> scroll to item 0 in section 2 to top
241
- # scroll_to_collection_view_item(5, 0, {:scroll_position => :bottom}) #=> scroll to item 5 in section 0 to bottom
509
+ # @example The following are the allowed :scroll_position values.
510
+ # {:top | :center_vertical | :bottom | :left | :center_horizontal | :right}
242
511
  #
243
- # allowed options
244
- # :query => a query string
245
- # default => 'collectionView'
246
- # example => "collectionView marked:'hit songs'"
512
+ # @param [Integer] item the index of the item to scroll to
513
+ # @param [Integer] section the section of the item to scroll to
514
+ # @param [Hash] opts options for controlling the collection view query
515
+ # and scroll behavior
247
516
  #
248
- # :scroll_position => the position to scroll to
249
- # default => :top
250
- # allowed => {:top | :center_vertical | :bottom | :left | :center_horizontal | :right}
517
+ # @option opts [String] :query ('collectionView')
518
+ # the query that is used to identify which collection view to scroll
251
519
  #
252
- # :animate => animate the scrolling
253
- # default => true
254
- # allowed => {true | false}
520
+ # @option opts [Symbol] :scroll_position (top)
521
+ # the position in the collection view to scroll the item to
255
522
  #
256
- # :failed_message => the message to display on failure
257
- # default => nil - will display a default failure message
258
- # allowed => any string
523
+ # @option opts [Boolean] :animate (true)
524
+ # should the scrolling be animated
259
525
  #
260
- # raises an exception if the scroll cannot be performed.
261
- # * the +:query+ finds no collection view
262
- # * collection view does not contain a cell at +item+/+section+
263
- # * +:scroll_position+ is invalid
526
+ # @option opts [String] :failed_message (nil)
527
+ # a custom error message to display if the scrolling fails - if not
528
+ # specified, a generic failure will be displayed
529
+ #
530
+ # @raise [RuntimeException] if the scroll cannot be performed
531
+ # @raise [RuntimeException] :query finds no collection view
532
+ # @raise [RuntimeException] the collection view does not contain a cell at item/section
533
+ # @raise [RuntimeException] :scroll_position is invalid
264
534
  def scroll_to_collection_view_item(item, section, opts={})
265
535
  default_options = {:query => 'collectionView',
266
536
  :scroll_position => :top,
@@ -289,35 +559,38 @@ module Calabash
289
559
  views_touched
290
560
  end
291
561
 
292
- # scrolls to +mark+ in a UICollectionView
293
- #
294
- # calls the +:collectionViewScrollToItemWithMark+ server route
562
+ # Scrolls to mark in a UICollectionView.
295
563
  #
296
- # scroll_to_collection_view_item_with_mark(mark, {:scroll_position => :top}) #=> scroll to the top of the item with the given +mark+
297
- # scroll_to_collection_view_item_with_mark(mark, {:scroll_position => :bottom}) #=> scroll to the bottom of the item with the given +mark+
564
+ # @example Scroll to the top of the item with the given mark.
565
+ # scroll_to_collection_view_item_with_mark('cat', {:scroll_position => :top})
298
566
  #
299
- # allowed options
300
- # :query => a query string
301
- # default => 'collectionView'
302
- # example => "collectionView marked:'hit songs'"
567
+ # @example Scroll to the bottom of the item with the given mark.
568
+ # scroll_to_collection_view_item_with_mark('dog', {:scroll_position => :bottom})
303
569
  #
304
- # :scroll_position => the position to scroll to
305
- # default => :top
306
- # allowed => {:top | :center_vertical | :bottom | :left | :center_horizontal | :right}
570
+ # @example The following are the allowed :scroll_position values.
571
+ # {:top | :center_vertical | :bottom | :left | :center_horizontal | :right}
307
572
  #
308
- # :animate => animate the scrolling
309
- # default => true
310
- # allowed => {true | false}
573
+ # @param [String] mark an accessibility `{label | identifier}` or text in
574
+ # or on the item
575
+ # @param [Hash] opts options for controlling the collection view query
576
+ # and scroll behavior
311
577
  #
312
- # :failed_message => the message to display on failure
313
- # default => nil - will display a default failure message
314
- # allowed => any string
578
+ # @option opts [String] :query ('collectionView')
579
+ # the query that is used to identify which collection view to scroll
580
+ # @option opts [Symbol] :scroll_position (:top)
581
+ # the position in the collection view to scroll the item to
582
+ # @option opts [Boolean] :animate (true) should the scroll
583
+ # be animated
584
+ # @option opts [String] :failed_message (nil)
585
+ # a custom error message to display if the scrolling fails - if not
586
+ # specified, a generic failure will be displayed
315
587
  #
316
- # raises an exception if the scroll cannot be performed.
317
- # * the +mark+ is nil
318
- # * the +:query+ finds no collection view
319
- # * collection view does not contain a cell with the given +mark+
320
- # * +:scroll_position+ is invalid
588
+ # @raise [RuntimeException] if the scroll cannot be performed
589
+ # @raise [RuntimeException] if the mark is nil
590
+ # @raise [RuntimeException] :query finds no collection view
591
+ # @raise [RuntimeException] the collection view does not contain a cell
592
+ # with the mark
593
+ # @raise [RuntimeException] :scroll_position is invalid
321
594
  def scroll_to_collection_view_item_with_mark(mark, opts={})
322
595
  default_options = {:query => 'collectionView',
323
596
  :scroll_position => :top,
@@ -346,10 +619,21 @@ module Calabash
346
619
  views_touched
347
620
  end
348
621
 
622
+ # Sends app to background. Simulates pressing the home button.
623
+ # @param {Fixnum} secs number of seconds to be in the background
624
+ # `should not be more than 60 secs`
349
625
  def send_app_to_background(secs)
350
626
  launcher.actions.send_app_to_background(secs)
351
627
  end
352
628
 
629
+ # Simulates gps location of the device/simulator.
630
+ # @note Seems UIAutomation is broken here on physical devices on iOS 7.1
631
+ # @example
632
+ # set_location place:'Tower of London'
633
+ # @param {Hash} options specifies which location to simulate
634
+ # @option options {String} :place a description of a place (resolved via Google maps api), e.g. "Tower of London"
635
+ # @option options {Numeric} :latitude latitude of a gps coordinate (same coordinate system as Google maps)
636
+ # @option options {Numeric} :longitude longitude of a gps coordinate (same coordinate system as Google maps)
353
637
  def set_location(options)
354
638
  if uia_available?
355
639
  uia_set_location(options)
@@ -377,16 +661,21 @@ module Calabash
377
661
  end
378
662
  end
379
663
 
664
+ # Returns a geo-location search result (via Google). Requires internet.
665
+ # @param {String} place a description of the place to search for
666
+ # @return {Geocoder::Result::Google} result of the search - see {http://www.rubygeocoder.com/}.
380
667
  def location_for_place(place)
381
668
  search_results = locations_for_place(place)
382
669
  raise "Got no results for #{place}" if search_results.empty?
383
670
  search_results.first
384
671
  end
385
672
 
673
+ # @!visibility private
386
674
  def locations_for_place(place)
387
675
  Geocoder.search(place)
388
676
  end
389
677
 
678
+ # @!visibility private
390
679
  def move_wheel(opts={})
391
680
  q = opts[:query] || 'pickerView'
392
681
  wheel = opts[:wheel] || 0
@@ -405,6 +694,7 @@ module Calabash
405
694
 
406
695
  end
407
696
 
697
+ # @!visibility private
408
698
  def picker(opts={:query => 'pickerView', :action => :texts})
409
699
  raise 'Not implemented' unless opts[:action] == :texts
410
700
 
@@ -438,6 +728,26 @@ module Calabash
438
728
  texts
439
729
  end
440
730
 
731
+ # Calls a method on the app's AppDelegate object.
732
+ #
733
+ # This is an escape hatch for calling an arbitrary hook inside
734
+ # (the test build) of your app. Commonly used to "go around" the UI for
735
+ # speed purposes or reset the app to a good known state.
736
+ #
737
+ # You must create a method on you app delegate of the form:
738
+ #
739
+ # - (NSString *) calabashBackdoor:(NSString *)aIgnorable;
740
+ #
741
+ # or if you want to pass parameters
742
+ #
743
+ # - (NSString *) calabashBackdoor:(NSDictionary *)params;
744
+ # @example
745
+ # backdoor("calabashBackdoor:", '')
746
+ # @example
747
+ # backdoor("calabashBackdoor:", {example:'param'})
748
+ # @param {String} sel the selector to perform on the app delegate
749
+ # @param {Object} arg the argument to pass to the selector
750
+ # @return {Object} the result of performing the selector with the argument (serialized)
441
751
  def backdoor(sel, arg)
442
752
  json = {
443
753
  :selector => sel,
@@ -451,6 +761,7 @@ module Calabash
451
761
  res['result']
452
762
  end
453
763
 
764
+ # Kills the app.
454
765
  def calabash_exit
455
766
  # Exiting the app shuts down the HTTP connection and generates ECONNREFUSED,
456
767
  # or HTTPClient::KeepAliveDisconnected
@@ -462,14 +773,19 @@ module Calabash
462
773
  end
463
774
  end
464
775
 
465
- def server_debug_level
776
+ # Get the Calabash server log level.
777
+ # @return {String} the current log level
778
+ def server_log_level
466
779
  _debug_level_response(http(:method => :get, :path => 'debug'))
467
780
  end
468
781
 
469
- def set_server_debug_level(level)
782
+ # Set the Calabash server log level.
783
+ # @param {String} level the log level to set (debug, info, warn, error)
784
+ def set_server_log_level(level)
470
785
  _debug_level_response(http({:method => :post, :path => 'debug'}, {:level => level}))
471
786
  end
472
787
 
788
+ # @!visibility private
473
789
  def _debug_level_response(json)
474
790
  res = JSON.parse(json)
475
791
  if res['outcome'] != 'SUCCESS'
@@ -477,8 +793,12 @@ module Calabash
477
793
  end
478
794
  res['results'].first
479
795
  end
480
- ## args :app for device bundle id, for sim path to app
481
- ##
796
+
797
+ # Starts the app and Calabash test server in the console.
798
+ # @note It is not recommended to call this method outside of the
799
+ # calabash console. Call `Calabash::Cucumber::Launcher#relaunch instead.
800
+ # @see Calabash::Cucumber::Launcher#relaunch
801
+ # @return {Calabash::Cucumber::Launcher} the launcher object in use
482
802
  def start_test_server_in_background(args={})
483
803
  stop_test_server
484
804
  @calabash_launcher = Calabash::Cucumber::Launcher.new()
@@ -486,26 +806,251 @@ module Calabash
486
806
  @calabash_launcher
487
807
  end
488
808
 
809
+ # Helper method to easily create page object instances from a cucumber execution context.
810
+ # The advantage of using `page` to instantiate a page object class is that it
811
+ # will automatically store a reference to the current Cucumber world
812
+ # which is needed in the page object methods to call Cucumber-specific methods
813
+ # like puts or embed.
814
+ # @example Instantiating a `LoginPage` from a step definition
815
+ # Given(/^I am about to login to a self-hosted site$/) do
816
+ # @current_page = page(LoginPage).await(timeout: 30)
817
+ # @current_page.self_hosted_site
818
+ # end
819
+ #
820
+ # @see Calabash::IBase
821
+ # @param {Class} clz the page object class to instantiate (passing the cucumber world and `args`)
822
+ # @param {Array} args optional additional arguments to pass to the page object constructor
823
+ # @return {Object} a fresh instance of `Class clz` which has been passed a reference to the cucumber World object.
824
+ def page(clz,*args)
825
+ clz.new(self,*args)
826
+ end
827
+
828
+ # Instantiates a page using `page` and calls the page's `await` method.
829
+ # @see #page
830
+ # @see Calabash::IBase#await
831
+ # @example Instantiating and waiting a `LoginPage` from a step definition
832
+ # Given(/^I am about to login to a self-hosted site$/) do
833
+ # @current_page = await_page(LoginPage)
834
+ # @current_page.self_hosted_site
835
+ # end
836
+ #
837
+ # @see Calabash::IBase
838
+ # @param {Class} clz the page object class to instantiate (passing the cucumber world and `args`)
839
+ # @param {Array} args optional additional arguments to pass to the page object constructor
840
+ # @return {Object} a fresh instance of `Class clz` which has been passed a reference to the cucumber World object.
841
+ # Calls await on the page object.
842
+ def await_page(clz,*args)
843
+ clz.new(self,*args).await
844
+ end
845
+
846
+ # @!visibility private
847
+ def home_direction
848
+ status_bar_orientation.to_sym
849
+ end
850
+
851
+ # Returns all accessibilityLabels of objects matching `uiquery`.
852
+ # @param {String} uiquery query to match
853
+ # @return {Array<String>} Returns all accessibilityLabels of objects matching `uiquery`.
854
+ def label(uiquery)
855
+ query(uiquery, :accessibilityLabel)
856
+ end
857
+
858
+ # Returns all accessibilityIdentifiers of objects matching `uiquery`.
859
+ # @param {String} uiquery query to match
860
+ # @return {Array<String>} Returns all accessibilityIdentifiers of objects matching `uiquery`.
861
+ def identifier(uiquery)
862
+ query(uiquery, :accessibilityIdentifier)
863
+ end
864
+
865
+ # @!visibility private
866
+ # @deprecated use `tap_mark`
867
+ def simple_touch(label, *args)
868
+ tap_mark(label, *args)
869
+ end
870
+
871
+ # taps a view with mark `hash_or_string`
872
+ # @deprecated In later Calabash versions we will change the semantics of `tap` to take a general query
873
+ # (instead of a 'mark' now). We're deprecating this now to prepare people for a breaking change.
874
+ # @param {String} hash_or_string mark to pass to call `tap_mark(hash_or_string)`.
875
+ # @return {Array<Hash>} array containing the serialized version of the tapped view.
876
+ def tap(hash_or_string, *args)
877
+ deprecation_msg = 'Use tap_mark instead. In later Calabash versions we will change the semantics of `tap` to take a general query.'
878
+ _deprecated('0.10.0', deprecation_msg, :warn)
879
+ if hash_or_string.is_a?(String)
880
+ tap_mark(hash_or_string, *args)
881
+ elsif hash_or_string.respond_to?(:[])
882
+ wait_tap(hash_or_string[:query], hash_or_string)
883
+ else
884
+ raise(ArgumentError, "first parameter to tap must be a string or a hash. Was: #{hash_or_string.class}, #{hash_or_string}")
885
+ end
886
+ end
887
+
888
+ # taps a view with mark `label`. Equivalent to `touch("* marked:'#{label}'")`
889
+ # @param {String} label the mark of the view to tap
890
+ # @param {Array} args optional additional arguments to pass to `touch`.
891
+ # @return {Array<Hash>} array containing the serialized version of the tapped view.
892
+ def tap_mark(label, *args)
893
+ touch("view marked:'#{label}'", *args)
894
+ end
895
+
896
+ # returns the 'html' property of all objects matching the query `q`
897
+ # @param {String} q the query to execute (should be a webView query)
898
+ # @return {Array<String>} array containing html of all elements matching the query
899
+ def html(q)
900
+ query(q).map { |e| e['html'] }
901
+ end
902
+
903
+ # sets the text value of the views matched by +uiquery+ to +txt+
904
+ #
905
+ # @deprecated since 0.9.145
906
+ #
907
+ # we have stopped testing this method. you have been warned.
908
+ #
909
+ # * to enter text using the native keyboard use 'keyboard_enter_text'
910
+ # * to delete text use 'keyboard_enter_text('Delete')"
911
+ # * to clear a text field or text view:
912
+ # - RECOMMENDED: use queries and touches to replicate what the user would do
913
+ # - for text fields, implement a clear text button and touch it
914
+ # - for text views, use touches to reveal text editing popup
915
+ # see https://github.com/calabash/calabash-ios/issues/151
916
+ # - use 'clear_text'
917
+ # https://github.com/calabash/calabash-ios/wiki/03.5-Calabash-iOS-Ruby-API
918
+ #
919
+ # raises an error if the +uiquery+ finds no matching queries or finds
920
+ # a view that does not respond to the objc selector 'setText'
921
+ def set_text(uiquery, txt)
922
+ msgs = ["'set_text' is deprecated and its behavior is now unpredictable",
923
+ "* to enter text using the native keyboard use 'keyboard_enter_text'",
924
+ "* to delete text use 'keyboard_enter_text('Delete')",
925
+ '* to clear a text field or text view:',
926
+ ' - RECOMMENDED: use queries and touches to replicate what the user would do',
927
+ ' * for text fields, implement a clear text button and touch it',
928
+ ' * for text views, use touches to reveal text editing popup',
929
+ ' see https://github.com/calabash/calabash-ios/issues/151',
930
+ " - use 'clear_text'",
931
+ 'https://github.com/calabash/calabash-ios/wiki/03.5-Calabash-iOS-Ruby-API']
932
+ msg = msgs.join("\n")
933
+ _deprecated('0.9.145', msg, :warn)
934
+
935
+ text_fields_modified = map(uiquery, :setText, txt)
936
+
937
+ msg = "query '#{uiquery}' returned no matching views that respond to 'setText'"
938
+ assert_map_results(text_fields_modified, msg)
939
+ text_fields_modified
940
+ end
941
+
942
+ # sets the text value of the views matched by +uiquery+ to <tt>''</tt>
943
+ # (the empty string)
944
+ #
945
+ # using this sparingly and with caution
946
+ #
947
+ #
948
+ # it is recommended that you instead do some combination of the following
949
+ #
950
+ # * use queries and touches to replicate with the user would
951
+ # - for text fields, implement a clear text button and touch it
952
+ # - for text views, use touches to reveal text editing popup
953
+ # see https://github.com/calabash/calabash-ios/issues/151
954
+ #
955
+ # https://github.com/calabash/calabash-ios/wiki/03.5-Calabash-iOS-Ruby-API
956
+ #
957
+ # raises an error if the +uiquery+ finds no matching queries or finds
958
+ # a _single_ view that does not respond to the objc selector 'setText'
959
+ #
960
+ # IMPORTANT
961
+ # calling:
962
+ #
963
+ # > clear_text("view")
964
+ #
965
+ # will clear the text on _all_ visible views that respond to 'setText'
966
+ def clear_text(uiquery)
967
+ views_modified = map(uiquery, :setText, '')
968
+ msg = "query '#{uiquery}' returned no matching views that respond to 'setText'"
969
+ assert_map_results(views_modified, msg)
970
+ views_modified
971
+ end
972
+
973
+
974
+ # Sets user preference (NSUserDefaults) value of key `key` to `val`.
975
+ # @example
976
+ # set_user_pref 'foo', {lastname: "Krukow"}
977
+ # # returns
978
+ # [
979
+ # {
980
+ # "lastname" => "Krukow"
981
+ # },
982
+ # {
983
+ # "firstname" => "Karl"
984
+ # }
985
+ # ]
986
+ #
987
+ # @param {String} key the set to set
988
+ # @param {Object} val the (JSON_ serializable) value to set
989
+ # @return {Object} the current user preferences
990
+ def set_user_pref(key, val)
991
+ res = http({:method => :post, :path => 'userprefs'},
992
+ {:key=> key, :value => val})
993
+ res = JSON.parse(res)
994
+ if res['outcome'] != 'SUCCESS'
995
+ screenshot_and_raise "set_user_pref #{key} = #{val} failed because: #{res['reason']}\n#{res['details']}"
996
+ end
997
+
998
+ res['results']
999
+ end
1000
+
1001
+ # Gets the user preference (NSUserDefaults) value for a key.
1002
+ # @param {String} key the read
1003
+ # @return {Object} the current user preferences value for `key`
1004
+ def user_pref(key)
1005
+ res = http({:method => :get, :raw => true, :path => 'userprefs'},
1006
+ {:key=> key})
1007
+ res = JSON.parse(res)
1008
+ if res['outcome'] != 'SUCCESS'
1009
+ screenshot_and_raise "get user_pref #{key} failed because: #{res['reason']}\n#{res['details']}"
1010
+ end
1011
+
1012
+ res['results'].first
1013
+ end
1014
+
1015
+ # @!visibility private
1016
+ # @todo broken currently
489
1017
  def stop_test_server
490
1018
  l = @calabash_launcher || Calabash::Cucumber::Launcher.launcher_if_used
491
1019
  l.stop if l
492
1020
  end
493
1021
 
1022
+ # @!visibility private
1023
+ # @todo broken currently
494
1024
  def shutdown_test_server
495
1025
  # Compat with Calabash Android
496
1026
  stop_test_server
497
1027
  end
498
1028
 
1029
+ # Attach the current calabash launcher to a console.
1030
+ # @example
1031
+ # You have encountered a failing cucumber Scenario.
1032
+ # You open the console and want to start investigating the cause of the failure.
1033
+ #
1034
+ # Use
1035
+ #
1036
+ # > console_attach
1037
+ #
1038
+ # to connect to the current launcher
1039
+ #
1040
+ # @return [Calabash::Cucumber::Launcher,nil] the currently active
1041
+ # calabash launcher
499
1042
  def console_attach
500
1043
  # setting the @calabash_launcher here for backward compatibility
501
1044
  @calabash_launcher = launcher.attach
502
1045
  end
503
1046
 
1047
+ # @!visibility private
504
1048
  def launcher
505
1049
  # setting the @calabash_launcher here for backward compatibility
506
1050
  @calabash_launcher = Calabash::Cucumber::Launcher.launcher
507
1051
  end
508
1052
 
1053
+ # @!visibility private
509
1054
  def query_action_with_options(action, uiquery, options)
510
1055
  uiquery, options = extract_query_and_options(uiquery, options)
511
1056
  views_touched = launcher.actions.send(action, options)
@@ -516,11 +1061,20 @@ module Calabash
516
1061
  views_touched
517
1062
  end
518
1063
 
1064
+ # @!visibility private
519
1065
  def extract_query_and_options(uiquery, options)
520
1066
  options = prepare_query_options(uiquery, options)
521
1067
  return options[:query], options
522
1068
  end
523
1069
 
1070
+ # @!visibility private
1071
+ def assert_home_direction(expected)
1072
+ unless expected.to_sym == home_direction
1073
+ screenshot_and_raise "Expected home button to have direction #{expected} but had #{home_direction}"
1074
+ end
1075
+ end
1076
+
1077
+ # @!visibility private
524
1078
  def prepare_query_options(uiquery, options)
525
1079
  opts = options.dup
526
1080
  if uiquery.is_a?(Array)