calabash 1.2.1 → 1.9.9.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +39 -0
  3. data/LICENSE +204 -21
  4. data/README.md +36 -6
  5. data/VERSIONING.md +16 -0
  6. data/bin/calabash +95 -0
  7. data/lib/calabash.rb +185 -1
  8. data/lib/calabash/android.rb +64 -0
  9. data/lib/calabash/android/adb.rb +277 -0
  10. data/lib/calabash/android/application.rb +110 -0
  11. data/lib/calabash/android/build.rb +12 -0
  12. data/lib/calabash/android/build/application.rb +13 -0
  13. data/lib/calabash/android/build/build_error.rb +11 -0
  14. data/lib/calabash/android/build/builder.rb +119 -0
  15. data/lib/calabash/android/build/java_keystore.rb +177 -0
  16. data/lib/calabash/android/build/resigner.rb +56 -0
  17. data/lib/calabash/android/build/test_server.rb +27 -0
  18. data/lib/calabash/android/console_helpers.rb +44 -0
  19. data/lib/calabash/android/cucumber.rb +3 -0
  20. data/lib/calabash/android/device.rb +965 -0
  21. data/lib/calabash/android/environment.rb +470 -0
  22. data/lib/calabash/android/gestures.rb +369 -0
  23. data/lib/calabash/android/interactions.rb +45 -0
  24. data/lib/calabash/android/lib/.irbrc +55 -0
  25. data/lib/calabash/android/lib/AndroidManifest.xml +51 -0
  26. data/lib/calabash/android/lib/TestServer.apk +0 -0
  27. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5 +0 -0
  28. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5-pie +0 -0
  29. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5 +0 -0
  30. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5-pie +0 -0
  31. data/lib/calabash/android/lib/calmd5/armeabi/calmd5 +0 -0
  32. data/lib/calabash/android/lib/calmd5/armeabi/calmd5-pie +0 -0
  33. data/lib/calabash/android/lib/calmd5/mips/calmd5 +0 -0
  34. data/lib/calabash/android/lib/calmd5/mips/calmd5-pie +0 -0
  35. data/lib/calabash/android/lib/calmd5/mips64/calmd5 +0 -0
  36. data/lib/calabash/android/lib/calmd5/mips64/calmd5-pie +0 -0
  37. data/lib/calabash/android/lib/calmd5/x86/calmd5 +0 -0
  38. data/lib/calabash/android/lib/calmd5/x86/calmd5-pie +0 -0
  39. data/lib/calabash/android/lib/calmd5/x86_64/calmd5 +0 -0
  40. data/lib/calabash/android/lib/calmd5/x86_64/calmd5-pie +0 -0
  41. data/lib/calabash/android/lib/screenshot_taker.jar +0 -0
  42. data/lib/calabash/android/life_cycle.rb +37 -0
  43. data/lib/calabash/android/orientation.rb +30 -0
  44. data/lib/calabash/android/physical_buttons.rb +39 -0
  45. data/lib/calabash/android/screenshot.rb +9 -0
  46. data/lib/calabash/android/scroll.rb +5 -0
  47. data/lib/calabash/android/server.rb +10 -0
  48. data/lib/calabash/android/text.rb +54 -0
  49. data/lib/calabash/application.rb +74 -0
  50. data/lib/calabash/cli.rb +12 -0
  51. data/lib/calabash/cli/build.rb +33 -0
  52. data/lib/calabash/cli/console.rb +90 -0
  53. data/lib/calabash/cli/generate.rb +110 -0
  54. data/lib/calabash/cli/helpers.rb +130 -0
  55. data/lib/calabash/cli/resign.rb +33 -0
  56. data/lib/calabash/cli/run.rb +99 -0
  57. data/lib/calabash/cli/setup_keystore.rb +39 -0
  58. data/lib/calabash/color.rb +32 -0
  59. data/lib/calabash/console_helpers.rb +90 -0
  60. data/lib/calabash/defaults.rb +56 -0
  61. data/lib/calabash/device.rb +401 -0
  62. data/lib/calabash/environment.rb +75 -0
  63. data/lib/calabash/gestures.rb +384 -0
  64. data/lib/calabash/http.rb +8 -0
  65. data/lib/calabash/http/error.rb +15 -0
  66. data/lib/calabash/http/request.rb +42 -0
  67. data/lib/calabash/http/retriable_client.rb +156 -0
  68. data/lib/calabash/interactions.rb +105 -0
  69. data/lib/calabash/ios.rb +37 -0
  70. data/lib/calabash/ios/application.rb +119 -0
  71. data/lib/calabash/ios/conditions.rb +79 -0
  72. data/lib/calabash/ios/console_helpers.rb +72 -0
  73. data/lib/calabash/ios/device.rb +24 -0
  74. data/lib/calabash/ios/device/device_implementation.rb +779 -0
  75. data/lib/calabash/ios/device/gestures_mixin.rb +167 -0
  76. data/lib/calabash/ios/device/keyboard_mixin.rb +133 -0
  77. data/lib/calabash/ios/device/physical_device_mixin.rb +266 -0
  78. data/lib/calabash/ios/device/rotation_mixin.rb +124 -0
  79. data/lib/calabash/ios/device/routes/backdoor_route_mixin.rb +86 -0
  80. data/lib/calabash/ios/device/routes/condition_route_mixin.rb +62 -0
  81. data/lib/calabash/ios/device/routes/error.rb +8 -0
  82. data/lib/calabash/ios/device/routes/handle_route_mixin.rb +102 -0
  83. data/lib/calabash/ios/device/routes/map_route_mixin.rb +38 -0
  84. data/lib/calabash/ios/device/routes/playback_route_mixin.rb +70 -0
  85. data/lib/calabash/ios/device/routes/response_parser.rb +48 -0
  86. data/lib/calabash/ios/device/routes/uia_route_mixin.rb +238 -0
  87. data/lib/calabash/ios/device/runtime_attributes.rb +184 -0
  88. data/lib/calabash/ios/device/status_bar_mixin.rb +17 -0
  89. data/lib/calabash/ios/device/text_mixin.rb +19 -0
  90. data/lib/calabash/ios/device/uia_keyboard_mixin.rb +188 -0
  91. data/lib/calabash/ios/device/uia_mixin.rb +12 -0
  92. data/lib/calabash/ios/environment.rb +41 -0
  93. data/lib/calabash/ios/interactions.rb +10 -0
  94. data/lib/calabash/ios/lib/.irbrc +55 -0
  95. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_ipad.base64 +2 -0
  96. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_iphone.base64 +2 -0
  97. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_ipad.base64 +2 -0
  98. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_iphone.base64 +2 -0
  99. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_ipad.base64 +2 -0
  100. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_iphone.base64 +2 -0
  101. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_ipad.base64 +2 -0
  102. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_iphone.base64 +2 -0
  103. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_ipad.base64 +2 -0
  104. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_iphone.base64 +2 -0
  105. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_ipad.base64 +2 -0
  106. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_iphone.base64 +2 -0
  107. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_ipad.base64 +2 -0
  108. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_iphone.base64 +2 -0
  109. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_ipad.base64 +2 -0
  110. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_iphone.base64 +2 -0
  111. data/lib/calabash/ios/orientation.rb +117 -0
  112. data/lib/calabash/ios/scroll.rb +504 -0
  113. data/lib/calabash/ios/server.rb +73 -0
  114. data/lib/calabash/ios/text.rb +248 -0
  115. data/lib/calabash/ios/uia.rb +24 -0
  116. data/lib/calabash/lib/skeleton/config/cucumber.yml +6 -0
  117. data/lib/calabash/lib/skeleton/features/sample.feature +5 -0
  118. data/lib/calabash/lib/skeleton/features/step_definitions/calabash_steps.rb +29 -0
  119. data/lib/calabash/lib/skeleton/features/support/env.rb +54 -0
  120. data/lib/calabash/lib/skeleton/features/support/hooks.rb +83 -0
  121. data/lib/calabash/life_cycle.rb +111 -0
  122. data/lib/calabash/location.rb +51 -0
  123. data/lib/calabash/logger.rb +87 -0
  124. data/lib/calabash/orientation.rb +84 -0
  125. data/lib/calabash/page.rb +35 -0
  126. data/lib/calabash/patch.rb +14 -0
  127. data/lib/calabash/patch/array.rb +16 -0
  128. data/lib/calabash/patch/run_loop.rb +90 -0
  129. data/lib/calabash/query.rb +160 -0
  130. data/lib/calabash/query_result.rb +85 -0
  131. data/lib/calabash/screenshot.rb +89 -0
  132. data/lib/calabash/server.rb +16 -0
  133. data/lib/calabash/text.rb +76 -0
  134. data/lib/calabash/utility.rb +58 -0
  135. data/lib/calabash/version.rb +3 -1
  136. data/lib/calabash/wait.rb +474 -0
  137. metadata +462 -24
@@ -0,0 +1,160 @@
1
+ module Calabash
2
+
3
+ # A representation of a Calabash query.
4
+ # @todo Query needs more documentation.
5
+ # @todo Query needs some methods moved to private or doc'd private.
6
+ class Query
7
+ # @!visibility private
8
+ def self.web_query?(query_string)
9
+ # :no, :double or :single
10
+ in_quotes = :no
11
+
12
+ # Number of slashes before the current char
13
+ slash_count = 0
14
+
15
+ # If the query starts with css: or xpath:
16
+ # We could change the regex from /(\s|\'|\")css:/ to /(^|\s|\'|\")css:/
17
+ # and change if (query[i, indicator[:length]] =~ indicator[:regex]) == 0
18
+ # to if (query[0, i+indicator[:length]] =~ indicator[:regex]) == i
19
+ # (not working)
20
+ # to avoid having to do this check.
21
+ results = WEB_QUERY_INDICATORS.map do |indicator|
22
+ query_string =~ /^\s*#{indicator[:string]}/
23
+ end
24
+
25
+ if results.any?
26
+ return true
27
+ end
28
+
29
+ length = query_string.length
30
+
31
+ length.times do |i|
32
+ char = query_string[i]
33
+
34
+ if char == "\\"
35
+ slash_count += 1
36
+ next
37
+ end
38
+
39
+ if char == "'"
40
+ if slash_count == 0
41
+ if in_quotes == :no
42
+ in_quotes = :single
43
+ elsif in_quotes == :single
44
+ in_quotes = :no
45
+ end
46
+ end
47
+ elsif char == '"'
48
+ if slash_count == 0
49
+ if in_quotes == :no
50
+ in_quotes = :double
51
+ elsif in_quotes == :double
52
+ in_quotes = :no
53
+ end
54
+ end
55
+ end
56
+
57
+ if slash_count == 0 && in_quotes == :no
58
+ WEB_QUERY_INDICATORS.each do |indicator|
59
+ if (query_string[i, indicator[:length]] =~ indicator[:regex]) == 0
60
+ return true
61
+ end
62
+ end
63
+ end
64
+
65
+ slash_count = 0
66
+ end
67
+
68
+ false
69
+ end
70
+
71
+ # @!visibility private
72
+ def self.query_hash_to_string(hash)
73
+ result = hash.fetch(:class, '*')
74
+
75
+ if hash[:marked] && (hash[:id] || hash[:text])
76
+ raise 'Cannot use both marked and id/text'
77
+ end
78
+
79
+ if hash[:marked]
80
+ result = "#{result} marked:'#{Text.escape_single_quotes(hash[:marked])}'"
81
+ end
82
+
83
+ if hash[:id]
84
+ result = "#{result} id:'#{Text.escape_single_quotes(hash[:id])}'"
85
+ end
86
+
87
+ if hash[:text]
88
+ result = "#{result} text:'#{Text.escape_single_quotes(hash[:text])}'"
89
+ end
90
+
91
+ if hash[:index]
92
+ result = "#{result} index:#{hash[:index]}"
93
+ end
94
+
95
+ if hash[:css]
96
+ result = "#{result} css:'#{Text.escape_single_quotes(hash[:css])}'"
97
+ end
98
+
99
+ if hash[:xpath]
100
+ result = "#{result} xpath:'#{Text.escape_single_quotes(hash[:xpath])}'"
101
+ end
102
+
103
+ result
104
+ end
105
+
106
+ def initialize(query)
107
+ unless query.is_a?(Query) || query.is_a?(Hash) || query.is_a?(String)
108
+ raise ArgumentError, "Invalid argument for query: '#{query}' (#{query.class})"
109
+ end
110
+
111
+ @query = query.dup
112
+
113
+ freeze
114
+ end
115
+
116
+ def to_s
117
+ if @query.is_a?(Query)
118
+ @query.to_s
119
+ elsif @query.is_a?(Hash)
120
+ Query.query_hash_to_string(@query)
121
+ else
122
+ @query.dup
123
+ end
124
+ end
125
+
126
+ def inspect
127
+ "<Calabash::Query #{@query.inspect}>"
128
+ end
129
+
130
+ def web_query?
131
+ Query.web_query?(to_s)
132
+ end
133
+
134
+ WEB_QUERY_INDICATORS =
135
+ [
136
+ {
137
+ string: 'css:',
138
+ regex: /(\s|\'|\")css:/,
139
+ length: 5
140
+ },
141
+ {
142
+ string: 'xpath:',
143
+ regex: /(\s|\'|\")xpath:/,
144
+ length: 7
145
+ }
146
+ ]
147
+
148
+ # @!visibility private
149
+ def self.valid_query?(query)
150
+ query.is_a?(String) || query.is_a?(Hash) || query.is_a?(Query)
151
+ end
152
+
153
+ # @!visibility private
154
+ def self.ensure_valid_query(query)
155
+ unless valid_query?(query)
156
+ raise ArgumentError, "invalid query '#{query}' (#{query.class})"
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,85 @@
1
+ module Calabash
2
+ # A QueryResult represents the returned value of a query.
3
+ # It is an immutable collection of matches or the result of applied methods.
4
+ # It will, unlike `Array`, raise an IndexError instead of returning nil if
5
+ # an entry outside bounds is accessed.
6
+ class QueryResult < Array
7
+ def self.create(result, query)
8
+ query_result = QueryResult.send(:new, query)
9
+ query_result.send(:initialize_copy, result)
10
+ recursive_freeze(query_result)
11
+ query_result
12
+ end
13
+
14
+ private_class_method :new
15
+
16
+ attr_reader :query
17
+
18
+ def initialize(query)
19
+ @query = Query.new(query)
20
+ end
21
+
22
+ def first(*several_variants)
23
+ ensure_in_bounds(0)
24
+
25
+ super(*several_variants)
26
+ end
27
+
28
+ def last(*several_variants)
29
+ ensure_in_bounds(-1)
30
+
31
+ super(*several_variants)
32
+ end
33
+
34
+ def [](index)
35
+ ensure_in_bounds(index)
36
+
37
+ super(index)
38
+ end
39
+
40
+ def at(index)
41
+ ensure_in_bounds(index)
42
+
43
+ super(index)
44
+ end
45
+
46
+ def fetch(*several_variants)
47
+ unless block_given? || several_variants.length > 1
48
+ ensure_in_bounds(several_variants.first)
49
+ end
50
+
51
+ super(*several_variants)
52
+ end
53
+
54
+ def ensure_in_bounds(index)
55
+ if empty?
56
+ raise IndexError, "Query result is empty"
57
+ end
58
+
59
+ if index > 0 && index >= length
60
+ raise IndexError, "Index out of bounds [index: #{index}, length: #{length}]"
61
+ end
62
+
63
+ if index < 0 && -index > length
64
+ raise IndexError, "Index out of bounds [index: #{index}, length: #{length}]"
65
+ end
66
+ end
67
+
68
+ def self.recursive_freeze(object)
69
+ if object.is_a?(Array)
70
+ object.each do |entry|
71
+ recursive_freeze(entry)
72
+ end
73
+ end
74
+
75
+ if object.is_a?(Hash)
76
+ object.each do |key, value|
77
+ recursive_freeze(key)
78
+ recursive_freeze(value)
79
+ end
80
+ end
81
+
82
+ object.freeze
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,89 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+
4
+ module Calabash
5
+
6
+ # A public API for taking screenshots.
7
+ module Screenshot
8
+ # @!visibility private
9
+ def self.screenshot_directory_prefix
10
+ @@screenshot_directory_prefix
11
+ end
12
+
13
+ # Set the screenshot directory prefix.
14
+ def self.screenshot_directory_prefix=(value)
15
+ if class_variable_defined?(:@@screenshots_taken) &&
16
+ @@screenshots_taken != 0
17
+ raise 'Cannot change the screenshot directory prefix after a screenshot has been taken'
18
+ end
19
+
20
+ @@screenshot_directory_prefix = value
21
+ end
22
+
23
+ # @!visibility private
24
+ self.screenshot_directory_prefix = 'test_run_'
25
+
26
+ # Takes a screenshot and saves it. The file is stored in the directory
27
+ # given by the ENV variable $CAL_SCREENSHOT_DIR, or by default in
28
+ # the relative directory 'screenshots'. The files are saved in a
29
+ # sub directory named test_run_n, where n is unique and incrementing for
30
+ # each new test run. The filename of the screenshot will be `name`.
31
+ # If `name` is not given (nil), the screenshot will be saved as
32
+ # screenshot_N, where N is the total amount of screenshots taken for the
33
+ # test run.
34
+ #
35
+ # @param [String] name Name of the screenshot.
36
+ # @return [String] Path to the screenshot
37
+ def screenshot(name=nil)
38
+ Device.default.screenshot(name)
39
+ end
40
+
41
+ # Takes a screenshot and embeds it in the test report.
42
+ # @see Screenshot#screenshot
43
+ def screenshot_embed(name=nil)
44
+ path = screenshot(name)
45
+ embed(path, 'image/png', name || File.basename(path))
46
+ end
47
+
48
+ # @!visibility private
49
+ def self.obtain_screenshot_path!(name=nil)
50
+ @@screenshots_taken ||= 1
51
+
52
+ if name.nil?
53
+ name = "screenshot_#{@@screenshots_taken}.png"
54
+ end
55
+
56
+ name = "#{name}.png" if File.extname(name).empty?
57
+
58
+ @@screenshots_taken += 1
59
+
60
+ unless Dir.exist?(File.expand_path(screenshot_directory))
61
+ FileUtils.mkdir_p(File.expand_path(screenshot_directory))
62
+ end
63
+
64
+ File.join(screenshot_directory, name)
65
+ end
66
+
67
+ # @!visibility private
68
+ def self.screenshot_directory
69
+ @@screenshot_directory ||= new_screenshot_sub_directory
70
+ end
71
+
72
+ # @!visibility private
73
+ def self.new_screenshot_sub_directory
74
+ count = screenshot_directory_test_run_directories.count
75
+ File.join(Environment::SCREENSHOT_DIRECTORY,
76
+ "#{screenshot_directory_prefix}#{count+1}")
77
+ end
78
+
79
+ # @!visibility private
80
+ def self.screenshot_directory_test_run_directories
81
+ dir = File.expand_path(File.join(Environment::SCREENSHOT_DIRECTORY, '*'))
82
+
83
+ Dir.glob(dir).select do |file|
84
+ File.directory?(file) &&
85
+ File.basename(file) =~ /^#{screenshot_directory_prefix}\d+$/
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,16 @@
1
+ module Calabash
2
+
3
+ # A representation of the Calabash test server.
4
+ class Server
5
+ attr_reader :endpoint
6
+ attr_reader :test_server_port
7
+
8
+ # @param [URI] endpoint The endpoint to reach the test server.
9
+ # @param [Integer] test_server_port The port bound to the test server
10
+ # running on the device. On iOS this is same as the endpoint port.
11
+ def initialize(endpoint, test_server_port = nil)
12
+ @endpoint = endpoint
13
+ @test_server_port = test_server_port || endpoint.port
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,76 @@
1
+ module Calabash
2
+
3
+ # A public API for entering text.
4
+ module Text
5
+ # Enter `text` into the currently focused view.
6
+ #
7
+ # @param [String] text The text to type.
8
+ # @raise [RuntimeError] if the text cannot be typed.
9
+ def enter_text(text)
10
+ Device.default.enter_text(text)
11
+ end
12
+
13
+ # Enter `text` into `query`.
14
+ # @see Calabash::Text#enter_text
15
+ #
16
+ # @param [String] text The text to type.
17
+ # @param query A query describing the view to enter text into.
18
+ def enter_text_in(query, text)
19
+ _enter_text_in(query, text)
20
+ end
21
+
22
+ # Clears the text of the currently focused view.
23
+ def clear_text
24
+ _clear_text
25
+ end
26
+
27
+ # Clears the text `view`
28
+ # @see Calabash::Text#clear_text
29
+ #
30
+ # @param query A query describing the view to clear text in.
31
+ def clear_text_in(view)
32
+ _clear_text_in(view)
33
+ end
34
+
35
+ # @todo add docs
36
+ def tap_current_keyboard_action_key
37
+ _tap_current_keyboard_action_key
38
+ end
39
+
40
+ # Escapes single quotes in `string`.
41
+ #
42
+ # @example
43
+ # > escape_quotes("Let's get this done.")
44
+ # => "Let\\'s get this done."
45
+ # @param [String] string The string to escape.
46
+ # @return [String] A string with its single quotes properly escaped.
47
+ def escape_single_quotes(string)
48
+ Text.escape_single_quotes(string)
49
+ end
50
+
51
+ # @!visibility private
52
+ def _enter_text_in(view, text)
53
+ abstract_method!
54
+ end
55
+
56
+ # @!visibility private
57
+ def _clear_text
58
+ abstract_method!
59
+ end
60
+
61
+ # @!visibility private
62
+ def _clear_text_in(view)
63
+ abstract_method!
64
+ end
65
+
66
+ # @!visibility private
67
+ def _tap_current_keyboard_action_key
68
+ abstract_method!
69
+ end
70
+
71
+ # @!visibility private
72
+ def self.escape_single_quotes(string)
73
+ string.gsub("'", "\\\\'")
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,58 @@
1
+ module Calabash
2
+
3
+ # @!visibility private
4
+ class AbstractMethodError < StandardError
5
+
6
+ end
7
+
8
+ module Utility
9
+
10
+ # @!visibility private
11
+ def abstract_method!
12
+ method_name = if Kernel.method_defined?(:caller_locations)
13
+ caller_locations.first.label
14
+ else
15
+ caller.first[/\`(.*)\'/, 1]
16
+ end
17
+
18
+ raise AbstractMethodError.new("Abstract method '#{method_name}'")
19
+ end
20
+
21
+ # @! visibility private
22
+ class RetryError < RuntimeError; end
23
+
24
+ # A convenience method for creating a percentage hash that that can be
25
+ # passed to gestures.
26
+ #
27
+ # @example
28
+ # # These are equivalent.
29
+ # pan(percent(20, 50), percent(20, 100))
30
+ # pan({x: 20, y: 50}, {x: 20, y: 100})
31
+ #
32
+ # @param [Number] x The value of the x percent.
33
+ # @param [Number] y The value of the y percent.
34
+ # @return [Hash] Representing the given values.
35
+ def percent(x, y)
36
+ {x: x, y: y}
37
+ end
38
+
39
+ alias_method :pct, :percent
40
+
41
+ # A convenience method for creating a coordinate hash that that can be
42
+ # passed to gestures.
43
+ #
44
+ # @example
45
+ # # These are equivalent.
46
+ # tap(query, offset: coordinate(20, 50))
47
+ # tap(query, offset: {x: 20, y: 50})
48
+ #
49
+ # @param [Number] x The value of the x.
50
+ # @param [Number] y The value of the y.
51
+ # @return [Hash] Representing the given values.
52
+ def coordinate(x, y)
53
+ {x: x, y: y}
54
+ end
55
+
56
+ alias_method :coord, :coordinate
57
+ end
58
+ end