forked from undees/justplayed
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathencumber.rb
274 lines (210 loc) · 5.82 KB
/
encumber.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
require 'enumerator'
require 'net/http'
require 'tagz'
require 'nokogiri'
module Net
class HTTP
def self.post_quick(url, body)
url = URI.parse url
req = Net::HTTP::Post.new url.path
req.body = body
http = Net::HTTP.new(url.host, url.port)
res = http.start do |sess|
sess.request req
end
res.body
end
end
end
module Encumber
class XcodeProject
def initialize path_for_xcode_project
@project = path_for_xcode_project
end
def set_target_for_simulator_debug name
set_target({
:name => name,
:config => 'Debug',
:sdk => 'iphonesimulator3.0',
:path_for_sdk => '/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/'
})
end
def set_target opt
@name_for_target = opt[:name]
@configuration_type = opt[:config]
@sdk = opt[:sdk]
@path_for_sdk = opt[:path_for_sdk]
%x{osascript<<APPLESCRIPT
tell application "Xcode"
set myProject to active project document
tell myProject
set the active target to the target named "#{@name_for_target}"
set active build configuration type to build configuration type "#{@configuration_type}"
set active SDK to "#{@sdk}"
set value of build setting "SDKROOT" of build configuration "#{@configuration_type}" of active target to "#{@path_for_sdk}"
end tell
end tell
APPLESCRIPT
2>&1}
end
def set_target_for_brominet
set_target_for_simulator_debug 'Brominet'
end
def start
%x{open #{@project}}
end
# This is a universal quit method, that leverages AppleScript to
# close any arbitrary application.
def quit name_for_app
status_for_quit = %x{osascript<<APPLESCRIPT
tell application "#{name_for_app}"
quit
end tell
APPLESCRIPT
2>&1}
sleep 7
status_for_quit
end
def quit_all
quit_simulator
quit_xcode
end
def quit_xcode
quit "Xcode"
end
def quit_simulator
quit "iPhone Simulator"
end
# Attempt to launch whichever build target is selected.
def launch_app_in_simulator
status_for_launch = %x{osascript<<APPLESCRIPT
tell application "Xcode"
set myProject to active project document
launch the active executable of myProject
end tell
APPLESCRIPT
2>&1}
sleep 7 unless status_for_launch =~ /Unable to launch executable./
status_for_launch
end
# Reset the iPhone simulator, removing all installed apps and
# settings. Great for teardowns.
#
# IMPORTANT: the elipsis in the Reset menu item name, is NOT three
# dots. It is a special Mac character: "…"
def reset_simulator
status_for_delete = %x{osascript<<APPLESCRIPT
activate application "iPhone Simulator"
tell application "System Events"
click menu item "Reset Content and Settings…" of menu "iPhone Simulator" of menu bar of process "iPhone Simulator"
tell process "iPhone Simulator"
tell window 1
click button 2
end tell
end tell
end tell
APPLESCRIPT
2>&1}
status_for_delete
end
end
class GUI
def initialize(host='localhost', port=50000, timeout_in_seconds=4)
@host, @port = host, port
@timeout = timeout_in_seconds
end
def command(name, *params)
raw = params.shift if params.first == :raw
command = Tagz.tagz do
plist_(:version => 1.0) do
dict_ do
key_ 'command'
string_ name
params.each_cons(2) do |k, v|
key_ k
raw ? tagz.concat(v) : string_(v)
end
end
end
end
Net::HTTP.post_quick \
"http://#{@host}:#{@port}/", command
end
def restart
begin
@gui.quit
rescue EOFError
# no-op
end
sleep 3
yield if block_given?
launch
end
def quit
command 'terminateApp'
end
def dump
command 'outputView'
end
def press(xpath)
command 'simulateTouch', 'viewXPath', xpath
end
# Nokogiri XML DOM for the current Brominet XML representation of the GUI
def dom_for_gui
@dom = Nokogiri::XML self.dump
end
# Idiomatic way to say wait_for_element
def wait_for xpath
wait_for_element xpath
end
# Wait for element. Returns an array of elements that match the
# xpath, or nil if nothing matches the xpath and the timeout
# period has expired.
#
# Note that there's no need to sleep between polls. At most, we
# can only poll about every other second, because it takes that
# long to request and receive the Brominet GUI XML.
def wait_for_element xpath
start_time_for_wait = Time.now
loop do
elements = dom_for_gui.search(xpath)
return elements unless elements.empty?
# Important: get the elapsed time AFTER getting the gui and
# evaluating the xpath.
elapsed_time_in_seconds = Time.now - start_time_for_wait
return nil if elapsed_time_in_seconds >= @timeout
end
end
def type_in_field text, xpath
command('setText',
'text', text,
'viewXPath', xpath)
sleep 1
end
# swipe to the right
def swipe xpath
command('simulateSwipe',
'viewXPath', xpath)
end
# swipe to the left
def swipe_left xpath
command('simulateLeftSwipe',
'viewXPath', xpath)
end
def swipe_and_wait xpath
swipe xpath
sleep 1
end
def swipe_left_and_wait xpath
swipe_left xpath
sleep 1
end
def tap xpath
press xpath
end
def tap_and_wait xpath
press xpath
sleep 1
end
end
end