calabash-cucumber 0.9.169.pre2 → 0.9.169.pre5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +14 -1
- data/bin/calabash-ios-setup.rb +2 -4
- data/bin/calabash-ios-sim.rb +10 -40
- data/calabash-cucumber.gemspec +25 -22
- data/features-skeleton/support/01_launch.rb +1 -1
- data/lib/calabash-cucumber.rb +13 -1
- data/lib/calabash-cucumber/actions/instruments_actions.rb +0 -4
- data/lib/calabash-cucumber/actions/playback_actions.rb +0 -4
- data/lib/calabash-cucumber/core.rb +9 -16
- data/lib/calabash-cucumber/device.rb +11 -2
- data/lib/calabash-cucumber/environment_helpers.rb +4 -56
- data/lib/calabash-cucumber/ios7_operations.rb +4 -2
- data/lib/calabash-cucumber/keyboard_helpers.rb +6 -3
- data/lib/calabash-cucumber/launch/simulator_helper.rb +40 -386
- data/lib/calabash-cucumber/launch/simulator_launcher.rb +534 -0
- data/lib/calabash-cucumber/launcher.rb +172 -36
- data/lib/calabash-cucumber/operations.rb +3 -4
- data/lib/calabash-cucumber/playback_helpers.rb +15 -29
- data/lib/calabash-cucumber/rotation_helpers.rb +14 -10
- data/lib/calabash-cucumber/status_bar_helpers.rb +5 -1
- data/lib/calabash-cucumber/uia.rb +6 -12
- data/lib/calabash-cucumber/utils/logging.rb +97 -0
- data/lib/calabash-cucumber/utils/plist_buddy.rb +178 -0
- data/lib/calabash-cucumber/utils/simulator_accessibility.rb +250 -0
- data/lib/calabash-cucumber/utils/xctools.rb +95 -0
- data/lib/calabash-cucumber/version.rb +197 -2
- data/lib/calabash-cucumber/wait_helpers.rb +16 -20
- data/scripts/.irbrc +11 -6
- data/scripts/com.example.plist +0 -0
- data/scripts/launch.rb +1 -1
- data/spec/bin/calabash_ios_sim_spec.rb +24 -0
- data/spec/launcher_spec.rb +76 -0
- data/spec/logging_spec.rb +38 -0
- data/spec/plist_buddy_spec.rb +99 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Default-568h@2x.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/Info.plist +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/LPSimpleExample-cal +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/PkgInfo +1 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/InfoPlist.strings +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFirstViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPFourthViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPSecondViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/en.lproj/LPThirdViewController~ipad.nib +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/first@2x.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second.png +0 -0
- data/spec/resources/enable-accessibility/LPSimpleExample-cal.app/second@2x.png +0 -0
- data/spec/resources/plist_buddy/com.example.plist +0 -0
- data/spec/resources/plist_buddy/com.testing.plist +18 -0
- data/spec/simulator_accessibility_spec.rb +144 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/xctools_spec.rb +58 -0
- metadata +120 -34
@@ -1,7 +1,11 @@
|
|
1
|
+
require 'calabash-cucumber/utils/logging'
|
2
|
+
|
1
3
|
module Calabash
|
2
4
|
module Cucumber
|
3
5
|
module RotationHelpers #=> Connection, StatusBarHelpers
|
4
6
|
|
7
|
+
include Calabash::Cucumber::Logging
|
8
|
+
|
5
9
|
def rotation_candidates
|
6
10
|
%w(rotate_left_home_down rotate_left_home_left rotate_left_home_right rotate_left_home_up
|
7
11
|
rotate_right_home_down rotate_right_home_left rotate_right_home_right rotate_right_home_up)
|
@@ -18,15 +22,15 @@ module Calabash
|
|
18
22
|
def rotate_home_button_to(dir)
|
19
23
|
dir_sym = dir.to_sym
|
20
24
|
if dir_sym.eql?(:top)
|
21
|
-
if
|
22
|
-
|
25
|
+
if full_console_logging?
|
26
|
+
calabash_warn "converting '#{dir}' to ':up' - please adjust your code"
|
23
27
|
end
|
24
28
|
dir_sym = :up
|
25
29
|
end
|
26
30
|
|
27
31
|
if dir_sym.eql?(:bottom)
|
28
|
-
if
|
29
|
-
|
32
|
+
if full_console_logging?
|
33
|
+
calabash_warn "converting '#{dir}' to ':down' - please adjust your code"
|
30
34
|
end
|
31
35
|
dir_sym = :down
|
32
36
|
end
|
@@ -46,7 +50,7 @@ module Calabash
|
|
46
50
|
return res if res.eql? dir_sym
|
47
51
|
|
48
52
|
rotation_candidates.each { |candidate|
|
49
|
-
if
|
53
|
+
if full_console_logging?
|
50
54
|
puts "try to rotate to '#{dir_sym}' using '#{candidate}'"
|
51
55
|
end
|
52
56
|
playback(candidate)
|
@@ -63,10 +67,10 @@ module Calabash
|
|
63
67
|
return if res.eql? dir_sym
|
64
68
|
}
|
65
69
|
|
66
|
-
if
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
+
if full_console_logging?
|
71
|
+
calabash_warn "Could not rotate home button to '#{dir}'."
|
72
|
+
calabash_warn 'Is rotation enabled for this controller?'
|
73
|
+
calabash_warn "Will return 'down'"
|
70
74
|
end
|
71
75
|
:down
|
72
76
|
end
|
@@ -99,7 +103,7 @@ module Calabash
|
|
99
103
|
end
|
100
104
|
|
101
105
|
if rotate_cmd.nil?
|
102
|
-
if
|
106
|
+
if full_console_logging?
|
103
107
|
puts "Could not rotate device in direction '#{dir}' with orientation '#{current_orientation} - will do nothing"
|
104
108
|
end
|
105
109
|
else
|
@@ -1,12 +1,16 @@
|
|
1
|
+
require 'calabash-cucumber/utils/logging'
|
2
|
+
|
1
3
|
module Calabash
|
2
4
|
module Cucumber
|
3
5
|
module StatusBarHelpers #=> Map
|
4
6
|
|
7
|
+
include Calabash::Cucumber::Logging
|
8
|
+
|
5
9
|
def device_orientation(force_down=false)
|
6
10
|
res = map(nil, :orientation, :device).first
|
7
11
|
|
8
12
|
if ['face up', 'face down'].include?(res)
|
9
|
-
if
|
13
|
+
if full_console_logging?
|
10
14
|
if force_down
|
11
15
|
puts "WARN found orientation '#{res}' - will rotate to force orientation to 'down'"
|
12
16
|
end
|
@@ -2,11 +2,14 @@ require 'edn'
|
|
2
2
|
require 'json'
|
3
3
|
# required for ruby 1.8
|
4
4
|
require 'enumerator'
|
5
|
+
require 'calabash-cucumber/utils/logging'
|
5
6
|
|
6
7
|
module Calabash
|
7
8
|
module Cucumber
|
8
9
|
module UIA
|
9
10
|
|
11
|
+
include Calabash::Cucumber::Logging
|
12
|
+
|
10
13
|
def uia(command,options={})
|
11
14
|
res = http({:method => :post, :path => 'uia'}, {:command => command}.merge(options))
|
12
15
|
res = JSON.parse(res)
|
@@ -16,15 +19,6 @@ module Calabash
|
|
16
19
|
res['results'].first
|
17
20
|
end
|
18
21
|
|
19
|
-
def uia_tap_server(query, options={})
|
20
|
-
res = http({:method => :post, :path => 'uia-tap'}, {:query => query}.merge(options))
|
21
|
-
res = JSON.parse(res)
|
22
|
-
if res['outcome'] != 'SUCCESS'
|
23
|
-
raise "uia-tap action failed because: #{res['reason']}\n#{res['details']}"
|
24
|
-
end
|
25
|
-
res['results'].first
|
26
|
-
end
|
27
|
-
|
28
22
|
def uia_query(*queryparts)
|
29
23
|
#TODO escape '\n etc in query
|
30
24
|
uia_handle_command(:query, queryparts)
|
@@ -201,7 +195,7 @@ module Calabash
|
|
201
195
|
end
|
202
196
|
end
|
203
197
|
command = "#{js_cmd}.#{js_args.join('.')}"
|
204
|
-
if
|
198
|
+
if debug_logging?
|
205
199
|
puts 'Sending UIA command'
|
206
200
|
puts command
|
207
201
|
end
|
@@ -212,7 +206,7 @@ module Calabash
|
|
212
206
|
|
213
207
|
def uia_handle_command(cmd, *query_args)
|
214
208
|
command = uia_serialize_command(cmd, *query_args)
|
215
|
-
if
|
209
|
+
if debug_logging?
|
216
210
|
puts 'Sending UIA command'
|
217
211
|
puts command
|
218
212
|
end
|
@@ -270,7 +264,7 @@ module Calabash
|
|
270
264
|
end
|
271
265
|
|
272
266
|
def uia_result(s)
|
273
|
-
if
|
267
|
+
if debug_logging?
|
274
268
|
puts 'Result'
|
275
269
|
p s
|
276
270
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
|
2
|
+
module Calabash
|
3
|
+
module Cucumber
|
4
|
+
|
5
|
+
# internal logging methods for calabash-ios gem
|
6
|
+
module Logging
|
7
|
+
|
8
|
+
# controls the the kind of information calabash logs
|
9
|
+
#
|
10
|
+
# this is considered one level above debug logging - maybe we should call
|
11
|
+
# the info log level.
|
12
|
+
#
|
13
|
+
# @return [Boolean] +true+ if the <tt>CALABASH_FULL_CONSOLE_OUTPUT</tt> is set to
|
14
|
+
# '1'
|
15
|
+
def full_console_logging?
|
16
|
+
ENV['CALABASH_FULL_CONSOLE_OUTPUT'] == '1'
|
17
|
+
end
|
18
|
+
|
19
|
+
# controls whether or not calabash logs debug information
|
20
|
+
#
|
21
|
+
# @return [Boolean] +true+ if the <tt>DEBUG</tt> is set to '1'
|
22
|
+
def debug_logging?
|
23
|
+
ENV['DEBUG'] == '1'
|
24
|
+
end
|
25
|
+
|
26
|
+
# prints a blue/cyan warning message
|
27
|
+
# @param [String] msg the message to print
|
28
|
+
def calabash_warn(msg)
|
29
|
+
begin
|
30
|
+
warn "\033[34m\nWARN: #{msg}\033[0m"
|
31
|
+
rescue
|
32
|
+
warn "\nWARN: #{msg}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# prints a green info message
|
37
|
+
# @param [String] msg the message to print
|
38
|
+
def calabash_info(msg)
|
39
|
+
begin
|
40
|
+
puts "\033[32m\nINFO: #{msg}\033[0m"
|
41
|
+
rescue
|
42
|
+
puts "\nINFO: #{msg}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# controls printing of deprecation warnings
|
47
|
+
#
|
48
|
+
# to inhibit deprecation message set this to '1'
|
49
|
+
#
|
50
|
+
# inhibiting deprecation messages is not recommend
|
51
|
+
CALABASH_NO_DEPRECATION = ENV['CALABASH_NO_DEPRECATION'] || '0'
|
52
|
+
|
53
|
+
# returns +true+ if the <tt>CALABASH_NO_DEPRECATION</tt> variable is set
|
54
|
+
# to +1+
|
55
|
+
def no_deprecation_warnings?
|
56
|
+
ENV['CALABASH_NO_DEPRECATION'] == '1'
|
57
|
+
end
|
58
|
+
|
59
|
+
# prints a deprecated message that includes the line number
|
60
|
+
#
|
61
|
+
# if ENV['CALABASH_NO_DEPRECATION'] == '1' then this method is a nop
|
62
|
+
#
|
63
|
+
# @param [String] version indicates when the feature was deprecated
|
64
|
+
# @param [String] msg deprecation message (possibly suggesting alternatives)
|
65
|
+
# @param [Symbol] type { :warn | :pending } - :pending will raise a
|
66
|
+
# cucumber pending exception
|
67
|
+
def _deprecated(version, msg, type)
|
68
|
+
allowed = [:pending, :warn]
|
69
|
+
unless allowed.include?(type)
|
70
|
+
raise "type '#{type}' must be on of '#{allowed}'"
|
71
|
+
end
|
72
|
+
|
73
|
+
unless no_deprecation_warnings?
|
74
|
+
|
75
|
+
if RUBY_VERSION < '2.0'
|
76
|
+
stack = Kernel.caller()[1..6].join("\n")
|
77
|
+
else
|
78
|
+
stack = Kernel.caller(0, 6)[1..-1].join("\n")
|
79
|
+
end
|
80
|
+
|
81
|
+
msg = "deprecated '#{version}' - '#{msg}'\n#{stack}"
|
82
|
+
|
83
|
+
if type.eql?(:pending)
|
84
|
+
pending(msg)
|
85
|
+
else
|
86
|
+
begin
|
87
|
+
warn "\033[34m\nWARN: #{msg}\033[0m"
|
88
|
+
rescue
|
89
|
+
warn "\nWARN: #{msg}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'calabash-cucumber/utils/logging'
|
2
|
+
|
3
|
+
module Calabash
|
4
|
+
module Cucumber
|
5
|
+
|
6
|
+
include Calabash::Cucumber::Logging
|
7
|
+
|
8
|
+
# module for reading and writing property list values
|
9
|
+
module PlistBuddy
|
10
|
+
|
11
|
+
# reads +key+ from +file+ and returns the result
|
12
|
+
# @param [String] key the key to inspect (may not be nil or empty)
|
13
|
+
# @param [String] file the plist to read
|
14
|
+
# @param [Hash] opts options for controlling execution
|
15
|
+
# @option opts [Boolean] :verbose (false) controls log level
|
16
|
+
# @return [nil] if +key+ does not exist
|
17
|
+
# @return [String] if the +key+ exists then the value of +key+ (error)
|
18
|
+
# @raise [ArgumentError] if nil or empty +key+
|
19
|
+
def plist_read(key, file, opts={})
|
20
|
+
if key.nil? or key.length == 0
|
21
|
+
raise(ArgumentError, "key '#{key}' must not be nil or empty")
|
22
|
+
end
|
23
|
+
cmd = build_plist_cmd(:print, {:key => key}, file)
|
24
|
+
res = execute_plist_cmd(cmd, opts)
|
25
|
+
if res == "Print: Entry, \":#{key}\", Does Not Exist"
|
26
|
+
nil
|
27
|
+
else
|
28
|
+
res
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# checks if the key exists in plist
|
33
|
+
# @param [String] key the key to inspect (may not be nil or empty)
|
34
|
+
# @param [String] file the plist to read
|
35
|
+
# @param [Hash] opts options for controlling execution
|
36
|
+
# @option opts [Boolean] :verbose (false) controls log level
|
37
|
+
# @return [Boolean] true iff the +key+ exists in plist +file+
|
38
|
+
def plist_key_exists?(key, file, opts={})
|
39
|
+
plist_read(key, file, opts) != nil
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
# replaces or creates the +value+ of +key+ in the +file+
|
44
|
+
#
|
45
|
+
# @param [String] key the key to set (may not be nil or empty)
|
46
|
+
# @param [String] type the plist type (used only when adding a value)
|
47
|
+
# @param [String] value the new value
|
48
|
+
# @param [String] file the plist to read
|
49
|
+
# @param [Hash] opts options for controlling execution
|
50
|
+
# @option opts [Boolean] :verbose (false) controls log level
|
51
|
+
# @return [Boolean] true iff the operation was successful
|
52
|
+
# @raise [ArgumentError] if nil or empty +key+
|
53
|
+
def plist_set(key, type, value, file, opts={})
|
54
|
+
default_opts = {:verbose => false}
|
55
|
+
merged = default_opts.merge(opts)
|
56
|
+
|
57
|
+
if key.nil? or key.length == 0
|
58
|
+
raise(ArgumentError, "key '#{key}' must not be nil or empty")
|
59
|
+
end
|
60
|
+
|
61
|
+
cmd_args = {:key => key,
|
62
|
+
:type => type,
|
63
|
+
:value => value}
|
64
|
+
|
65
|
+
if plist_key_exists?(key, file, merged)
|
66
|
+
cmd = build_plist_cmd(:set, cmd_args, file)
|
67
|
+
else
|
68
|
+
cmd = build_plist_cmd(:add, cmd_args, file)
|
69
|
+
end
|
70
|
+
|
71
|
+
res = execute_plist_cmd(cmd, merged)
|
72
|
+
res == ''
|
73
|
+
end
|
74
|
+
|
75
|
+
@private
|
76
|
+
|
77
|
+
# returns the path to the PlistBuddy executable
|
78
|
+
# @return [String] path to PlistBuddy
|
79
|
+
def plist_buddy
|
80
|
+
'/usr/libexec/PlistBuddy'
|
81
|
+
end
|
82
|
+
|
83
|
+
# executes +cmd+ as a shell command and returns the result
|
84
|
+
#
|
85
|
+
# @param [String] cmd shell command to execute
|
86
|
+
# @param [Hash] opts options for controlling execution
|
87
|
+
# @option opts [Boolean] :verbose (false) controls log level
|
88
|
+
# @return [Boolean] if command was successful
|
89
|
+
# @return [String] if :print'ing result, the value of the key
|
90
|
+
# @return [String] if there is an error, the output from stderr
|
91
|
+
def execute_plist_cmd(cmd, opts={})
|
92
|
+
default_opts = {:verbose => false}
|
93
|
+
merged = default_opts.merge(opts)
|
94
|
+
|
95
|
+
calabash_info(cmd) if merged[:verbose]
|
96
|
+
|
97
|
+
res = nil
|
98
|
+
# noinspection RubyUnusedLocalVariable
|
99
|
+
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
100
|
+
err = stderr.read
|
101
|
+
std = stdout.read
|
102
|
+
if not err.nil? and err != ''
|
103
|
+
res = err.chomp
|
104
|
+
else
|
105
|
+
res = std.chomp
|
106
|
+
end
|
107
|
+
end
|
108
|
+
res
|
109
|
+
end
|
110
|
+
|
111
|
+
# composes a PlistBuddy command that can be executed as a shell command
|
112
|
+
#
|
113
|
+
# @param [Symbol] type should be one of [:print, :set, :add]
|
114
|
+
#
|
115
|
+
# @param [Hash] args_hash arguments used to construct plist command
|
116
|
+
# @option args_hash [String] :key (required) the plist key
|
117
|
+
# @option args_hash [String] :value (required for :set and :add) the new value
|
118
|
+
# @option args_hash [String] :type (required for :add) the new type of the value
|
119
|
+
#
|
120
|
+
# @param [String] file the plist file to interact with (must exist)
|
121
|
+
#
|
122
|
+
# @raise [RuntimeError] if +file+ does not exist
|
123
|
+
# @raise [ArgumentError] when invalid +type+ is passed
|
124
|
+
# @raise [ArgumentError] when +args_hash+ does not include required key/value pairs
|
125
|
+
#
|
126
|
+
# @return [String] a shell-ready PlistBuddy command
|
127
|
+
def build_plist_cmd(type, args_hash, file)
|
128
|
+
|
129
|
+
unless File.exist?(File.expand_path(file))
|
130
|
+
raise(RuntimeError, "plist '#{file}' does not exist - could not read")
|
131
|
+
end
|
132
|
+
|
133
|
+
case type
|
134
|
+
when :add
|
135
|
+
value_type = args_hash[:type]
|
136
|
+
unless value_type
|
137
|
+
raise(ArgumentError, ':value_type is a required key for :add command')
|
138
|
+
end
|
139
|
+
allowed_value_types = ['string', 'bool', 'real', 'integer']
|
140
|
+
unless allowed_value_types.include?(value_type)
|
141
|
+
raise(ArgumentError, "expected '#{value_type}' to be one of '#{allowed_value_types}'")
|
142
|
+
end
|
143
|
+
value = args_hash[:value]
|
144
|
+
unless value
|
145
|
+
raise(ArgumentError, ':value is a required key for :add command')
|
146
|
+
end
|
147
|
+
key = args_hash[:key]
|
148
|
+
unless key
|
149
|
+
raise(ArgumentError, ':key is a required key for :add command')
|
150
|
+
end
|
151
|
+
cmd_part = "\"Add :#{key} #{value_type} #{value}\""
|
152
|
+
when :print
|
153
|
+
key = args_hash[:key]
|
154
|
+
unless key
|
155
|
+
raise(ArgumentError, ':key is a required key for :print command')
|
156
|
+
end
|
157
|
+
cmd_part = "\"Print :#{key}\""
|
158
|
+
when :set
|
159
|
+
value = args_hash[:value]
|
160
|
+
unless value
|
161
|
+
raise(ArgumentError, ':value is a required key for :set command')
|
162
|
+
end
|
163
|
+
key = args_hash[:key]
|
164
|
+
unless key
|
165
|
+
raise(ArgumentError, ':key is a required key for :set command')
|
166
|
+
end
|
167
|
+
cmd_part = "\"Set :#{key} #{value}\""
|
168
|
+
else
|
169
|
+
cmds = [:add, :print, :set]
|
170
|
+
raise(ArgumentError, "expected '#{type}' to be one of '#{cmds}'")
|
171
|
+
end
|
172
|
+
|
173
|
+
"#{plist_buddy} -c #{cmd_part} \"#{file}\""
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'calabash-cucumber/utils/xctools'
|
2
|
+
require 'calabash-cucumber/utils/plist_buddy'
|
3
|
+
require 'sim_launcher'
|
4
|
+
|
5
|
+
module Calabash
|
6
|
+
module Cucumber
|
7
|
+
|
8
|
+
# methods for checking and setting simulator accessibility
|
9
|
+
module SimulatorAccessibility
|
10
|
+
|
11
|
+
include Calabash::Cucumber::XcodeTools
|
12
|
+
include Calabash::Cucumber::PlistBuddy
|
13
|
+
|
14
|
+
# quits the iOS Simulator
|
15
|
+
#
|
16
|
+
# ATM there can only be only simulator open at a time, so simply doing
|
17
|
+
# what the sim_launcher gem does:
|
18
|
+
#
|
19
|
+
# def quit_simulator
|
20
|
+
# `echo 'application "iPhone Simulator" quit' | osascript`
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# works. I am not sure if we will ever be able to launch more than one
|
24
|
+
# simulator, but in case we can, this method will quit the simulator
|
25
|
+
# that is indicated by +xcode-select+ or +DEVELOPER_DIR+.
|
26
|
+
def quit_simulator
|
27
|
+
dev_dir = xcode_developer_dir
|
28
|
+
system "/usr/bin/osascript -e 'tell application \"#{dev_dir}/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app\" to quit'"
|
29
|
+
end
|
30
|
+
|
31
|
+
# launches the iOS Simulator indicated by +xcode-select+ or +DEVELOPER_DIR+
|
32
|
+
def launch_simulator
|
33
|
+
dev_dir = xcode_developer_dir
|
34
|
+
system "open -a \"#{dev_dir}/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app\""
|
35
|
+
end
|
36
|
+
|
37
|
+
# resets the simulator content and settings. it is analogous to touching
|
38
|
+
# the menu item.
|
39
|
+
#
|
40
|
+
# it works by deleting the following directories:
|
41
|
+
#
|
42
|
+
# * ~/Library/Application Support/iPhone Simulator/Library
|
43
|
+
# * ~/Library/Application Support/iPhone Simulator/Library/<sdk>[-64]
|
44
|
+
#
|
45
|
+
# and relaunching the iOS Simulator which will recreate the Library
|
46
|
+
# directory and the latest SDK directory.
|
47
|
+
def reset_simulator_content_and_settings
|
48
|
+
quit_simulator
|
49
|
+
sim_lib_path = File.join(simulator_app_support_dir(), 'Library')
|
50
|
+
FileUtils.rm_rf(sim_lib_path)
|
51
|
+
simulator_support_sdk_dirs.each do |dir|
|
52
|
+
FileUtils.rm_rf(dir)
|
53
|
+
end
|
54
|
+
|
55
|
+
launch_simulator
|
56
|
+
|
57
|
+
# this is tricky because we need to wait for the simulator to recreate
|
58
|
+
# the directories. specifically, we need the Accessibility plist to be
|
59
|
+
# exist so subsequent calabash launches will be able to enable
|
60
|
+
# accessibility.
|
61
|
+
#
|
62
|
+
# the directories take ~3.0 - ~5.0 to create.
|
63
|
+
counter = 0
|
64
|
+
loop do
|
65
|
+
break if counter == 80
|
66
|
+
dirs = simulator_support_sdk_dirs
|
67
|
+
if dirs.count == 0
|
68
|
+
sleep(0.2)
|
69
|
+
else
|
70
|
+
break if dirs.all? { |dir|
|
71
|
+
plist = File.expand_path("#{dir}/Library/Preferences/com.apple.Accessibility.plist")
|
72
|
+
File.exists?(plist)
|
73
|
+
}
|
74
|
+
sleep(0.2)
|
75
|
+
end
|
76
|
+
counter = counter + 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# enables accessibility on any existing iOS Simulator by adjusting the
|
81
|
+
# simulator's Library/Preferences/com.apple.Accessibility.plist contents.
|
82
|
+
#
|
83
|
+
# a simulator 'exists' if has an Application Support directory. for
|
84
|
+
# example, the 6.1, 7.0.3-64, and 7.1 simulators exist if the following
|
85
|
+
# directories are present:
|
86
|
+
#
|
87
|
+
# ~/Library/Application Support/iPhone Simulator/Library/6.1
|
88
|
+
# ~/Library/Application Support/iPhone Simulator/Library/7.0.3-64
|
89
|
+
# ~/Library/Application Support/iPhone Simulator/Library/7.1
|
90
|
+
#
|
91
|
+
# this method also hides the AXInspector.
|
92
|
+
# @param [Hash] opts controls the behavior of the method
|
93
|
+
# @option opts [Boolean] :verbose controls logging output
|
94
|
+
# @return [Boolean] true iff enabling accessibility worked on all sdk
|
95
|
+
# directories
|
96
|
+
def enable_accessibility_on_simulators(opts={})
|
97
|
+
results = simulator_support_sdk_dirs.map do |dir|
|
98
|
+
enable_accessibility_in_sdk_dir(dir, opts)
|
99
|
+
end
|
100
|
+
results.all? { |elm| elm }
|
101
|
+
end
|
102
|
+
|
103
|
+
@private
|
104
|
+
|
105
|
+
# enables accessibility on the simulator indicated by
|
106
|
+
# +sim_app_support_sdk_dir+.
|
107
|
+
#
|
108
|
+
# WARNING: this will quit the simulator
|
109
|
+
#
|
110
|
+
# path = '~/Library/Application Support/iPhone Simulator/Library/6.1'
|
111
|
+
# enable_accessibility_in_sdk_dir(path)
|
112
|
+
#
|
113
|
+
# this method also hides the AXInspector.
|
114
|
+
#
|
115
|
+
# if the Library/Preferences/com.apple.Accessibility.plist does not exist,
|
116
|
+
# this method returns false.
|
117
|
+
#
|
118
|
+
# @see enable_accessibility_on_simulators for the public API.
|
119
|
+
#
|
120
|
+
# @param [String] sim_app_support_sdk_dir the directory where the
|
121
|
+
# Library/Preferences/com.apple.Accessibility.plist can be found.
|
122
|
+
#
|
123
|
+
# @param [Hash] opts controls the behavior of the method
|
124
|
+
# @option opts [Boolean] :verbose controls logging output
|
125
|
+
# @return [Boolean] iff the plist exists and the plist was successfully
|
126
|
+
# updated.
|
127
|
+
def enable_accessibility_in_sdk_dir(sim_app_support_sdk_dir, opts={})
|
128
|
+
default_opts = {:verbose => false}
|
129
|
+
merged = default_opts.merge(opts)
|
130
|
+
|
131
|
+
plist_path = File.expand_path("#{sim_app_support_sdk_dir}/Library/Preferences/com.apple.Accessibility.plist")
|
132
|
+
|
133
|
+
verbose = merged[:verbose]
|
134
|
+
|
135
|
+
sdk = File.basename(sim_app_support_sdk_dir)
|
136
|
+
msgs = ["cannot enable accessibility for #{sdk} SDK"]
|
137
|
+
unless File.exists?(plist_path)
|
138
|
+
if verbose
|
139
|
+
msgs << "expected plist to exist at #{plist_path}"
|
140
|
+
calabash_warn(msgs.join("\n"))
|
141
|
+
end
|
142
|
+
return false
|
143
|
+
end
|
144
|
+
|
145
|
+
quit_simulator
|
146
|
+
|
147
|
+
hash = accessibility_properties_hash()
|
148
|
+
|
149
|
+
unless plist_set(hash[:access_enabled], 'bool', 'true', plist_path)
|
150
|
+
if verbose
|
151
|
+
msgs << "could not set '#{hash[:access_enabled]}' to YES"
|
152
|
+
calabash_warn(msgs.join("\n"))
|
153
|
+
end
|
154
|
+
return false
|
155
|
+
end
|
156
|
+
|
157
|
+
unless plist_set(hash[:app_access_enabled], 'bool', 'true', plist_path)
|
158
|
+
if verbose
|
159
|
+
msgs << "could not set '#{hash[:app_access_enabled]}' to YES"
|
160
|
+
calabash_warn(msgs.join("\n"))
|
161
|
+
end
|
162
|
+
return false
|
163
|
+
end
|
164
|
+
|
165
|
+
unless plist_set(hash[:automation_enabled], 'bool', 'true', plist_path)
|
166
|
+
if verbose
|
167
|
+
msgs << "could not set '#{hash[:automation_enabled]}' to YES"
|
168
|
+
calabash_warn(msgs.join("\n"))
|
169
|
+
end
|
170
|
+
return false
|
171
|
+
end
|
172
|
+
|
173
|
+
unless plist_set(hash[:inspector_showing], 'bool', 'false', plist_path)
|
174
|
+
if verbose
|
175
|
+
msgs << "could not set '#{hash[:inspector_showing]}' to NO"
|
176
|
+
calabash_warn(msgs.join("\n"))
|
177
|
+
end
|
178
|
+
return false
|
179
|
+
end
|
180
|
+
|
181
|
+
unless plist_set(hash[:inspector_full_size], 'bool', 'false', plist_path)
|
182
|
+
if verbose
|
183
|
+
msgs << "could not set '#{hash[:inspector_full_size]}' to NO"
|
184
|
+
calabash_warn(msgs.join("\n"))
|
185
|
+
end
|
186
|
+
return false
|
187
|
+
end
|
188
|
+
|
189
|
+
res = plist_set(hash[:inspector_frame], 'string', '{{270, -13}, {276, 166}}', plist_path)
|
190
|
+
unless res
|
191
|
+
if verbose
|
192
|
+
msgs << "could not set '#{hash[:inspector_frame]}'"
|
193
|
+
calabash_warn(msgs.join("\n"))
|
194
|
+
end
|
195
|
+
end
|
196
|
+
res
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
# a hash table of the accessibility properties that control whether or not
|
201
|
+
# accessibility is enabled and whether the AXInspector is visible.
|
202
|
+
# @return [Hash] table of accessibility properties found in the
|
203
|
+
# Library/Preferences/com.apple.Accessibility.plist
|
204
|
+
def accessibility_properties_hash
|
205
|
+
{
|
206
|
+
# this is required
|
207
|
+
:access_enabled => 'AccessibilityEnabled',
|
208
|
+
# i _think_ this is legacy
|
209
|
+
:app_access_enabled => 'ApplicationAccessibilityEnabled',
|
210
|
+
|
211
|
+
# i don't know what this does
|
212
|
+
:automation_enabled => 'AutomationEnabled',
|
213
|
+
|
214
|
+
# determines if the Accessibility Inspector is showing
|
215
|
+
:inspector_showing => 'AXInspectorEnabled',
|
216
|
+
# controls if the Accessibility Inspector is expanded or not expanded
|
217
|
+
:inspector_full_size => 'AXInspector.enabled',
|
218
|
+
# controls the frame of the Accessibility Inspector
|
219
|
+
# this is a 'string' => {{0, 0}, {276, 166}}
|
220
|
+
:inspector_frame => 'AXInspector.frame'
|
221
|
+
}
|
222
|
+
end
|
223
|
+
|
224
|
+
# the absolute path the the iPhone Simulator Application Support directory
|
225
|
+
# @return [String] absolute path
|
226
|
+
def simulator_app_support_dir
|
227
|
+
File.expand_path('~/Library/Application Support/iPhone Simulator')
|
228
|
+
end
|
229
|
+
|
230
|
+
# returns a list of absolute paths the existing simulator directories.
|
231
|
+
#
|
232
|
+
# a simulator 'exists' if has an Application Support directory. for
|
233
|
+
# example, the 6.1, 7.0.3-64, and 7.1 simulators exist if the following
|
234
|
+
# directories are present:
|
235
|
+
#
|
236
|
+
# ~/Library/Application Support/iPhone Simulator/Library/6.1
|
237
|
+
# ~/Library/Application Support/iPhone Simulator/Library/7.0.3-64
|
238
|
+
# ~/Library/Application Support/iPhone Simulator/Library/7.1
|
239
|
+
#
|
240
|
+
# @return[Array<String>] a list of absolute paths to simulator directories
|
241
|
+
def simulator_support_sdk_dirs
|
242
|
+
sim_app_support_path = simulator_app_support_dir()
|
243
|
+
Dir.glob("#{sim_app_support_path}/*").select { |path|
|
244
|
+
path =~ /(\d)\.(\d)\.?(\d)?(-64)?/
|
245
|
+
}
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|