xcmonkey 1.1.0 → 1.2.0
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/README.md +3 -3
- data/lib/xcmonkey/driver.rb +63 -29
- data/lib/xcmonkey/version.rb +1 -1
- data/spec/describer_spec.rb +4 -2
- data/spec/driver_spec.rb +70 -28
- data/spec/xcmonkey_spec.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c93c94403332c085a393877d88d354b2736788f6e52d118eb8b9faa70c91b1e5
|
4
|
+
data.tar.gz: ee0f3bfcd014151b4821a6df50f601205581ebd480b5626e33588bda2928981a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ab88db343b0e83363130a9e9c8ed965acbf9d58f56d597b301ff12da4df9d4e79b08c3b2284b870a65c9bfc3d05a8ba9df0d19409631620a28836c9d5785814
|
7
|
+
data.tar.gz: fe46af5c215273be9210f3c880617457a12c6063e0bd1901d6abbd10750f10935b77a4797ff374926c3f1cac6b1ef79032f210fb705e05917146e4c64cede97c
|
data/README.md
CHANGED
@@ -39,7 +39,7 @@ gem 'xcmonkey'
|
|
39
39
|
### To run a stress test
|
40
40
|
|
41
41
|
```bash
|
42
|
-
xcmonkey test --
|
42
|
+
$ xcmonkey test --duration 100 --bundle-id "com.apple.Maps" --udid "413EA256-CFFB-4312-94A6-12592BEE4CBA"
|
43
43
|
|
44
44
|
12:44:19.343: Device info: {
|
45
45
|
"name": "iPhone 14 Pro",
|
@@ -106,9 +106,9 @@ require 'xcmonkey'
|
|
106
106
|
|
107
107
|
lane :test do
|
108
108
|
Xcmonkey.new(
|
109
|
-
|
109
|
+
duration: 100,
|
110
110
|
bundle_id: 'com.apple.Maps',
|
111
|
-
|
111
|
+
udid: '413EA256-CFFB-4312-94A6-12592BEE4CBA'
|
112
112
|
).run
|
113
113
|
end
|
114
114
|
```
|
data/lib/xcmonkey/driver.rb
CHANGED
@@ -16,15 +16,16 @@ class Driver
|
|
16
16
|
puts
|
17
17
|
ensure_device_exists
|
18
18
|
ensure_app_installed
|
19
|
-
terminate_app
|
20
|
-
|
21
|
-
|
19
|
+
terminate_app(bundle_id)
|
20
|
+
launch_app(target_bundle_id: bundle_id, wait_for_state_update: true)
|
21
|
+
@running_apps = list_running_apps
|
22
22
|
end
|
23
23
|
|
24
24
|
def monkey_test(gestures)
|
25
25
|
monkey_test_precondition
|
26
26
|
app_elements = describe_ui.shuffle
|
27
27
|
current_time = Time.now
|
28
|
+
counter = 0
|
28
29
|
while Time.now < current_time + session_duration
|
29
30
|
el1_coordinates = central_coordinates(app_elements.first)
|
30
31
|
el2_coordinates = central_coordinates(app_elements.last)
|
@@ -52,17 +53,17 @@ class Driver
|
|
52
53
|
else
|
53
54
|
next
|
54
55
|
end
|
56
|
+
detect_app_state_change
|
57
|
+
track_running_apps if counter % 5 == 0 # Track running apps after every 5th action to speed up the test
|
58
|
+
counter += 1
|
55
59
|
app_elements = describe_ui.shuffle
|
56
|
-
next unless app_elements.include?(@home_tracker)
|
57
|
-
|
58
|
-
save_session
|
59
|
-
Logger.error('App lost')
|
60
60
|
end
|
61
61
|
save_session
|
62
62
|
end
|
63
63
|
|
64
64
|
def repeat_monkey_test
|
65
65
|
monkey_test_precondition
|
66
|
+
counter = 0
|
66
67
|
session_actions.each do |action|
|
67
68
|
case action['type']
|
68
69
|
when 'tap'
|
@@ -78,15 +79,12 @@ class Driver
|
|
78
79
|
else
|
79
80
|
next
|
80
81
|
end
|
81
|
-
|
82
|
+
detect_app_state_change
|
83
|
+
track_running_apps if counter % 5 == 0
|
84
|
+
counter += 1
|
82
85
|
end
|
83
86
|
end
|
84
87
|
|
85
|
-
def open_home_screen(with_tracker: false)
|
86
|
-
`idb ui button --udid #{udid} HOME`
|
87
|
-
detect_home_unique_element if with_tracker
|
88
|
-
end
|
89
|
-
|
90
88
|
def describe_ui
|
91
89
|
JSON.parse(`idb ui describe-all --udid #{udid}`)
|
92
90
|
end
|
@@ -97,13 +95,13 @@ class Driver
|
|
97
95
|
point_info
|
98
96
|
end
|
99
97
|
|
100
|
-
def launch_app
|
101
|
-
`idb launch --udid #{udid} #{
|
102
|
-
wait_until_app_launched
|
98
|
+
def launch_app(target_bundle_id:, wait_for_state_update: false)
|
99
|
+
`idb launch --udid #{udid} #{target_bundle_id}`
|
100
|
+
wait_until_app_launched(target_bundle_id) if wait_for_state_update
|
103
101
|
end
|
104
102
|
|
105
|
-
def terminate_app
|
106
|
-
`idb terminate --udid #{udid} #{
|
103
|
+
def terminate_app(target_bundle_id)
|
104
|
+
`idb terminate --udid #{udid} #{target_bundle_id} 2>/dev/null`
|
107
105
|
end
|
108
106
|
|
109
107
|
def boot_simulator
|
@@ -130,6 +128,10 @@ class Driver
|
|
130
128
|
`idb list-apps --udid #{udid} --json`.split("\n").map! { |app| JSON.parse(app) }
|
131
129
|
end
|
132
130
|
|
131
|
+
def list_running_apps
|
132
|
+
list_apps.select { |app| app['process_state'] == 'Running' }
|
133
|
+
end
|
134
|
+
|
133
135
|
def ensure_app_installed
|
134
136
|
return if list_apps.any? { |app| app['bundle_id'] == bundle_id }
|
135
137
|
|
@@ -144,6 +146,9 @@ class Driver
|
|
144
146
|
if device['type'] == 'simulator'
|
145
147
|
configure_simulator_keyboard
|
146
148
|
boot_simulator
|
149
|
+
else
|
150
|
+
Logger.error('xcmonkey does not support real devices yet. ' \
|
151
|
+
'For more information see https://github.com/alteral/xcmonkey/issues/7')
|
147
152
|
end
|
148
153
|
end
|
149
154
|
|
@@ -220,28 +225,57 @@ class Driver
|
|
220
225
|
File.write("#{session_path}/xcmonkey-session.json", JSON.pretty_generate(@session))
|
221
226
|
end
|
222
227
|
|
223
|
-
|
228
|
+
# This function takes ≈200ms
|
229
|
+
def track_running_apps
|
230
|
+
current_list_of_running_apps = list_running_apps
|
231
|
+
if @running_apps != current_list_of_running_apps
|
232
|
+
currently_running_bundle_ids = current_list_of_running_apps.map { |app| app['bundle_id'] }
|
233
|
+
previously_running_bundle_ids = @running_apps.map { |app| app['bundle_id'] }
|
234
|
+
new_apps = currently_running_bundle_ids - previously_running_bundle_ids
|
224
235
|
|
225
|
-
|
226
|
-
|
236
|
+
return if new_apps.empty?
|
237
|
+
|
238
|
+
launch_app(target_bundle_id: bundle_id)
|
239
|
+
new_apps.each do |id|
|
240
|
+
Logger.warn("Shutting down: #{id}")
|
241
|
+
terminate_app(id)
|
242
|
+
end
|
243
|
+
end
|
227
244
|
end
|
228
245
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
246
|
+
# This function takes ≈300ms
|
247
|
+
def detect_app_state_change
|
248
|
+
return unless detect_app_in_background
|
249
|
+
|
250
|
+
target_app_is_running = list_running_apps.any? { |app| app['bundle_id'] == bundle_id }
|
251
|
+
|
252
|
+
if target_app_is_running
|
253
|
+
launch_app(target_bundle_id: bundle_id)
|
254
|
+
else
|
255
|
+
save_session
|
256
|
+
Logger.error("Target app has crashed or been terminated")
|
233
257
|
end
|
234
|
-
@home_tracker
|
235
258
|
end
|
236
259
|
|
237
|
-
def
|
260
|
+
def detect_app_in_background
|
261
|
+
current_app_label = describe_ui.detect { |el| el['type'] == 'Application' }['AXLabel']
|
262
|
+
current_app_label.nil? || current_app_label.strip.empty?
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
def ensure_driver_installed
|
268
|
+
Logger.error("'idb' doesn't seem to be installed") if `which idb`.strip.empty?
|
269
|
+
end
|
270
|
+
|
271
|
+
def wait_until_app_launched(target_bundle_id)
|
238
272
|
app_is_running = false
|
239
273
|
current_time = Time.now
|
240
274
|
while !app_is_running && Time.now < current_time + 5
|
241
|
-
app_info = list_apps.detect { |app| app['bundle_id'] ==
|
275
|
+
app_info = list_apps.detect { |app| app['bundle_id'] == target_bundle_id }
|
242
276
|
app_is_running = app_info && app_info['process_state'] == 'Running'
|
243
277
|
end
|
244
|
-
Logger.error("Can't run the app #{
|
278
|
+
Logger.error("Can't run the app #{target_bundle_id}") unless app_is_running
|
245
279
|
Logger.info('App info:', payload: JSON.pretty_generate(app_info))
|
246
280
|
end
|
247
281
|
end
|
data/lib/xcmonkey/version.rb
CHANGED
data/spec/describer_spec.rb
CHANGED
@@ -2,15 +2,17 @@ describe Describer do
|
|
2
2
|
let(:udid) { `xcrun simctl list | grep " iPhone 14 Pro Max"`.split("\n")[0].split('(')[1].split(')')[0] }
|
3
3
|
let(:driver) { Driver.new(udid: udid) }
|
4
4
|
|
5
|
-
|
5
|
+
before do
|
6
6
|
allow(Logger).to receive(:info)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'verifies that point can be described (integer)' do
|
7
10
|
driver.boot_simulator
|
8
11
|
point_info = described_class.new(udid: udid, x: 10, y: 10).run
|
9
12
|
expect(point_info).not_to be_empty
|
10
13
|
end
|
11
14
|
|
12
15
|
it 'verifies that point can be described (string)' do
|
13
|
-
allow(Logger).to receive(:info)
|
14
16
|
driver.boot_simulator
|
15
17
|
point_info = described_class.new(udid: udid, x: '10', y: '10').run
|
16
18
|
expect(point_info).not_to be_empty
|
data/spec/driver_spec.rb
CHANGED
@@ -4,6 +4,10 @@ describe Driver do
|
|
4
4
|
let(:driver) { described_class.new(udid: udid, bundle_id: bundle_id, session_path: Dir.pwd) }
|
5
5
|
let(:driver_with_session) { described_class.new(udid: udid, bundle_id: bundle_id, session_actions: [{ type: 'tap', x: 0, y: 0 }]) }
|
6
6
|
|
7
|
+
before do
|
8
|
+
allow(Logger).to receive(:info)
|
9
|
+
end
|
10
|
+
|
7
11
|
it 'verifies that sumulator was booted' do
|
8
12
|
error_message = "Failed to boot #{udid}"
|
9
13
|
expect(Logger).not_to receive(:error).with(error_message, payload: nil)
|
@@ -16,18 +20,6 @@ describe Driver do
|
|
16
20
|
expect(ui).not_to be_empty
|
17
21
|
end
|
18
22
|
|
19
|
-
it 'verifies that home screen can be opened' do
|
20
|
-
driver.boot_simulator
|
21
|
-
home_tracker = driver.open_home_screen(with_tracker: true)
|
22
|
-
expect(home_tracker).not_to be_empty
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'verifies that home screen can be opened without tracker' do
|
26
|
-
driver.boot_simulator
|
27
|
-
home_tracker = driver.open_home_screen(with_tracker: false)
|
28
|
-
expect(home_tracker).to be_nil
|
29
|
-
end
|
30
|
-
|
31
23
|
it 'verifies that list of targets can be showed' do
|
32
24
|
list_targets = driver.list_targets
|
33
25
|
expect(list_targets).not_to be_empty
|
@@ -56,9 +48,7 @@ describe Driver do
|
|
56
48
|
end
|
57
49
|
|
58
50
|
it 'verifies that device exists' do
|
59
|
-
payload = driver.list_targets.detect { |target| target['udid'] == udid }
|
60
51
|
expect(Logger).not_to receive(:error)
|
61
|
-
expect(Logger).to receive(:info).with('Device info:', payload: JSON.pretty_generate(payload))
|
62
52
|
expect(driver).to receive(:boot_simulator)
|
63
53
|
expect(driver).to receive(:configure_simulator_keyboard)
|
64
54
|
expect { driver.ensure_device_exists }.not_to raise_error
|
@@ -137,18 +127,25 @@ describe Driver do
|
|
137
127
|
expect(keyboard_state.first).to include('1')
|
138
128
|
end
|
139
129
|
|
140
|
-
it 'verifies that app can be launched' do
|
130
|
+
it 'verifies that app can be launched with waiting' do
|
131
|
+
expect(Logger).not_to receive(:error)
|
132
|
+
expect(driver).to receive(:wait_until_app_launched)
|
133
|
+
driver.boot_simulator
|
134
|
+
driver.terminate_app(bundle_id)
|
135
|
+
expect { driver.launch_app(target_bundle_id: bundle_id, wait_for_state_update: true) }.not_to raise_error
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'verifies that app can be launched without waiting' do
|
141
139
|
expect(Logger).not_to receive(:error)
|
142
|
-
expect(
|
140
|
+
expect(driver).not_to receive(:wait_until_app_launched)
|
143
141
|
driver.boot_simulator
|
144
|
-
driver.terminate_app
|
145
|
-
expect { driver.launch_app }.not_to raise_error
|
142
|
+
driver.terminate_app(bundle_id)
|
143
|
+
expect { driver.launch_app(target_bundle_id: bundle_id) }.not_to raise_error
|
146
144
|
end
|
147
145
|
|
148
146
|
it 'verifies tap in new session' do
|
149
147
|
driver.boot_simulator
|
150
148
|
coordinates = { x: 1, y: 1 }
|
151
|
-
expect(Logger).to receive(:info).with('Tap:', payload: JSON.pretty_generate(coordinates))
|
152
149
|
driver.tap(coordinates: coordinates)
|
153
150
|
expect(driver.instance_variable_get(:@session)[:actions]).not_to be_empty
|
154
151
|
end
|
@@ -156,7 +153,6 @@ describe Driver do
|
|
156
153
|
it 'verifies tap in old session' do
|
157
154
|
driver_with_session.boot_simulator
|
158
155
|
coordinates = { x: 1, y: 1 }
|
159
|
-
expect(Logger).to receive(:info).with('Tap:', payload: JSON.pretty_generate(coordinates))
|
160
156
|
driver_with_session.tap(coordinates: coordinates)
|
161
157
|
expect(driver_with_session.instance_variable_get(:@session)[:actions]).to be_empty
|
162
158
|
end
|
@@ -165,7 +161,6 @@ describe Driver do
|
|
165
161
|
driver.boot_simulator
|
166
162
|
duration = 0.5
|
167
163
|
coordinates = { x: 1, y: 1 }
|
168
|
-
expect(Logger).to receive(:info).with("Press (#{duration}s):", payload: JSON.pretty_generate(coordinates))
|
169
164
|
driver.press(coordinates: coordinates, duration: duration)
|
170
165
|
expect(driver.instance_variable_get(:@session)[:actions]).not_to be_empty
|
171
166
|
end
|
@@ -174,7 +169,6 @@ describe Driver do
|
|
174
169
|
driver_with_session.boot_simulator
|
175
170
|
duration = 0.5
|
176
171
|
coordinates = { x: 1, y: 1 }
|
177
|
-
expect(Logger).to receive(:info).with("Press (#{duration}s):", payload: JSON.pretty_generate(coordinates))
|
178
172
|
driver_with_session.press(coordinates: coordinates, duration: duration)
|
179
173
|
expect(driver_with_session.instance_variable_get(:@session)[:actions]).to be_empty
|
180
174
|
end
|
@@ -184,7 +178,6 @@ describe Driver do
|
|
184
178
|
duration = 0.5
|
185
179
|
start_coordinates = { x: 1, y: 1 }
|
186
180
|
end_coordinates = { x: 2, y: 2 }
|
187
|
-
expect(Logger).to receive(:info).with("Swipe (#{duration}s):", payload: "#{JSON.pretty_generate(start_coordinates)} => #{JSON.pretty_generate(end_coordinates)}")
|
188
181
|
driver.swipe(start_coordinates: start_coordinates, end_coordinates: end_coordinates, duration: duration)
|
189
182
|
expect(driver.instance_variable_get(:@session)[:actions]).not_to be_empty
|
190
183
|
end
|
@@ -194,7 +187,6 @@ describe Driver do
|
|
194
187
|
duration = 0.5
|
195
188
|
start_coordinates = { x: 1, y: 1 }
|
196
189
|
end_coordinates = { x: 2, y: 2 }
|
197
|
-
expect(Logger).to receive(:info).with("Swipe (#{duration}s):", payload: "#{JSON.pretty_generate(start_coordinates)} => #{JSON.pretty_generate(end_coordinates)}")
|
198
190
|
driver_with_session.swipe(start_coordinates: start_coordinates, end_coordinates: end_coordinates, duration: duration)
|
199
191
|
expect(driver_with_session.instance_variable_get(:@session)[:actions]).to be_empty
|
200
192
|
end
|
@@ -210,12 +202,12 @@ describe Driver do
|
|
210
202
|
app_info = driver.list_apps.detect { |app| app['bundle_id'] == bundle_id }
|
211
203
|
app_is_running = app_info && app_info['process_state'] == 'Running'
|
212
204
|
expect(app_is_running).to be(true)
|
205
|
+
expect(driver.instance_variable_get(:@running_apps)).not_to be_nil
|
213
206
|
end
|
214
207
|
|
215
208
|
it 'verifies that monkey_test works fine' do
|
216
209
|
params = { udid: udid, bundle_id: bundle_id, duration: 1, session_path: Dir.pwd }
|
217
210
|
driver = described_class.new(params)
|
218
|
-
expect(driver).to receive(:monkey_test_precondition)
|
219
211
|
driver.monkey_test(Xcmonkey.new(params).gestures)
|
220
212
|
expect(driver.instance_variable_get(:@session)[:actions]).not_to be_empty
|
221
213
|
end
|
@@ -227,8 +219,6 @@ describe Driver do
|
|
227
219
|
{ 'type' => 'swipe', 'x' => 12, 'y' => 12, 'endX' => 15, 'endY' => 15, 'duration' => 0.3 }
|
228
220
|
]
|
229
221
|
driver = described_class.new(udid: udid, bundle_id: bundle_id, session_actions: session_actions)
|
230
|
-
allow(Logger).to receive(:info).twice
|
231
|
-
expect(driver).to receive(:monkey_test_precondition)
|
232
222
|
expect(driver).to receive(:tap).with(coordinates: { x: 10, y: 10 })
|
233
223
|
expect(driver).to receive(:press).with(coordinates: { x: 11, y: 11 }, duration: 1.4)
|
234
224
|
expect(driver).to receive(:swipe).with(start_coordinates: { x: 12, y: 12 }, end_coordinates: { x: 15, y: 15 }, duration: 0.3)
|
@@ -238,7 +228,6 @@ describe Driver do
|
|
238
228
|
|
239
229
|
it 'verifies that unknown actions does not break repeat_monkey_test' do
|
240
230
|
driver = described_class.new(udid: udid, bundle_id: bundle_id, session_actions: [{ 'type' => 'test', 'x' => 10, 'y' => 10 }])
|
241
|
-
allow(Logger).to receive(:info).twice
|
242
231
|
expect(driver).to receive(:monkey_test_precondition)
|
243
232
|
expect(driver).not_to receive(:tap)
|
244
233
|
expect(driver).not_to receive(:press)
|
@@ -247,6 +236,59 @@ describe Driver do
|
|
247
236
|
expect(driver.instance_variable_get(:@session)[:actions]).to be_empty
|
248
237
|
end
|
249
238
|
|
239
|
+
it 'verifies that running apps are tracked' do
|
240
|
+
new_app_bundle_id = 'com.apple.Preferences'
|
241
|
+
driver.terminate_app(new_app_bundle_id)
|
242
|
+
driver.monkey_test_precondition
|
243
|
+
driver.launch_app(target_bundle_id: new_app_bundle_id, wait_for_state_update: true)
|
244
|
+
expect(driver).to receive(:launch_app).with(target_bundle_id: bundle_id)
|
245
|
+
expect(driver).to receive(:terminate_app).with(new_app_bundle_id)
|
246
|
+
driver.track_running_apps
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'verifies that running apps can be determined' do
|
250
|
+
driver.terminate_app(bundle_id)
|
251
|
+
sum = driver.list_running_apps.size
|
252
|
+
driver.launch_app(target_bundle_id: bundle_id)
|
253
|
+
expect(driver.list_running_apps.size).to eq(sum + 1)
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'verifies that app state change can be determined' do
|
257
|
+
driver.launch_app(target_bundle_id: bundle_id)
|
258
|
+
allow(driver).to receive(:detect_app_in_background).and_return(true)
|
259
|
+
expect(driver).not_to receive(:save_session)
|
260
|
+
expect(driver).to receive(:launch_app)
|
261
|
+
expect { driver.detect_app_state_change }.not_to raise_error
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'verifies that background is the invalid app state' do
|
265
|
+
driver.terminate_app(bundle_id)
|
266
|
+
expect(driver).to receive(:save_session)
|
267
|
+
expect { driver.detect_app_state_change }.to raise_error(SystemExit) { |e| expect(e.status).to eq(1) }
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'verifies that foreground is the valid app state' do
|
271
|
+
driver.launch_app(target_bundle_id: bundle_id, wait_for_state_update: true)
|
272
|
+
expect { driver.detect_app_state_change }.not_to raise_error
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'verifies that background state can be determined' do
|
276
|
+
driver.terminate_app(bundle_id)
|
277
|
+
expect(driver.detect_app_in_background).to be(true)
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'verifies that foregroung state can be determined' do
|
281
|
+
driver.monkey_test_precondition
|
282
|
+
expect(driver.detect_app_in_background).to be(false)
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'verifies that xcmonkey behaves as expected on real devices' do
|
286
|
+
udid = '1234-5678'
|
287
|
+
driver = described_class.new(udid: udid, bundle_id: bundle_id)
|
288
|
+
allow(driver).to receive(:list_targets).and_return([{ 'udid' => udid, 'type' => 'device' }])
|
289
|
+
expect { driver.ensure_device_exists }.to raise_error(SystemExit) { |e| expect(e.status).to eq(1) }
|
290
|
+
end
|
291
|
+
|
250
292
|
it 'verifies that simulator was not booted' do
|
251
293
|
driver.shutdown_simulator
|
252
294
|
error_message = "Failed to boot #{udid}"
|
data/spec/xcmonkey_spec.rb
CHANGED
@@ -2,6 +2,10 @@ describe Xcmonkey do
|
|
2
2
|
let(:params) { { udid: '123', bundle_id: 'example.com.app', duration: 10, session_path: Dir.pwd } }
|
3
3
|
let(:duration_error_msg) { 'Duration must be Integer and not less than 1 second' }
|
4
4
|
|
5
|
+
before do
|
6
|
+
allow(Logger).to receive(:info)
|
7
|
+
end
|
8
|
+
|
5
9
|
it 'verifies gestures' do
|
6
10
|
gestures = described_class.new(params).gestures
|
7
11
|
taps = [:precise_tap, :blind_tap] * 10
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xcmonkey
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- alteral
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|