xcmonkey 1.0.0 → 1.1.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/.github/{issue_template → ISSUE_TEMPLATE}/bug_report.md +0 -0
- data/.github/{issue_template/feature_request.md → ISSUE_TEMPLATE/feature-request.md} +1 -1
- data/.github/workflows/test.yml +3 -2
- data/README.md +42 -50
- data/bin/xcmonkey +1 -6
- data/lib/xcmonkey/describer.rb +16 -16
- data/lib/xcmonkey/driver.rb +19 -19
- data/lib/xcmonkey/repeater.rb +28 -28
- data/lib/xcmonkey/version.rb +2 -3
- data/lib/xcmonkey.rb +26 -25
- data/spec/driver_spec.rb +48 -12
- data/spec/repeater_spec.rb +0 -1
- data/spec/xcmonkey_spec.rb +49 -55
- data/xcmonkey.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d3bd605b57ec05a83a3cca39707b5c2fc9529828131b9ac872f3dc478180bbb
|
4
|
+
data.tar.gz: 8793e64f73775a2c8de84d1b79d0aebd258df7c22b9c8f43de2618f63f306d4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e4634518e71dac0ed206d4fec26fc707fb9dbea8116c87db1959695261e8ee311246db203317790433d18b5e5250074f1f17bf567101dfec6767a1ed5db0670
|
7
|
+
data.tar.gz: 0e696e9804b94e6106f203b9bcda008f57dbe7fbda78a68ff7d57a8cfa980e4b691b533f430bac855ae8ed56ae0e7ac5085f305853bae8f03652095871287a94
|
File without changes
|
data/.github/workflows/test.yml
CHANGED
@@ -17,10 +17,11 @@ jobs:
|
|
17
17
|
env:
|
18
18
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
19
19
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
20
|
+
PR_NUMBER: ${{ github.event.number }}
|
20
21
|
steps:
|
21
|
-
- uses: actions/checkout@v3.
|
22
|
+
- uses: actions/checkout@v3.3.0
|
22
23
|
|
23
|
-
- uses: actions/setup-python@v4.
|
24
|
+
- uses: actions/setup-python@v4.5.0
|
24
25
|
with:
|
25
26
|
python-version: 3.11
|
26
27
|
cache: 'pip'
|
data/README.md
CHANGED
@@ -39,10 +39,32 @@ gem 'xcmonkey'
|
|
39
39
|
### To run a stress test
|
40
40
|
|
41
41
|
```bash
|
42
|
-
|
43
|
-
|
42
|
+
xcmonkey test --udid "413EA256-CFFB-4312-94A6-12592BEE4CBA" --bundle-id "com.apple.Maps" --duration 100
|
43
|
+
|
44
|
+
12:44:19.343: Device info: {
|
45
|
+
"name": "iPhone 14 Pro",
|
46
|
+
"udid": "413EA256-CFFB-4312-94A6-12592BEE4CBA",
|
47
|
+
"state": "Booted",
|
48
|
+
"type": "simulator",
|
49
|
+
"os_version": "iOS 16.2",
|
50
|
+
"architecture": "x86_64",
|
51
|
+
"path": "/tmp/idb/413EA256-CFFB-4312-94A6-12592BEE4CBA_companion.sock",
|
52
|
+
"is_local": true,
|
53
|
+
"companion": "/tmp/idb/413EA256-CFFB-4312-94A6-12592BEE4CBA_companion.sock"
|
54
|
+
}
|
44
55
|
|
45
|
-
12:44:22.550: App info:
|
56
|
+
12:44:22.550: App info: {
|
57
|
+
"bundle_id": "com.apple.Maps",
|
58
|
+
"name": "Maps",
|
59
|
+
"install_type": "system",
|
60
|
+
"architectures": [
|
61
|
+
"x86_64",
|
62
|
+
"arm64"
|
63
|
+
],
|
64
|
+
"process_state": "Running",
|
65
|
+
"debuggable": false,
|
66
|
+
"pid": "49186"
|
67
|
+
}
|
46
68
|
|
47
69
|
12:44:23.203: Tap: {
|
48
70
|
"x": 53,
|
@@ -66,59 +88,29 @@ $ xcmonkey test --udid "413EA256-CFFB-4312-94A6-12592BEE4CBA" --bundle-id "com.a
|
|
66
88
|
### To repeat the stress test from generated session
|
67
89
|
|
68
90
|
```bash
|
69
|
-
|
70
|
-
12:48:13.333: Device info: iPhone 14 Pro | 413EA256-CFFB-4312-94A6-12592BEE4CBA | Booted | simulator | iOS 16.2 | x86_64 | /tmp/idb/413EA256-CFFB-4312-94A6-12592BEE4CBA_companion.sock
|
71
|
-
|
72
|
-
12:48:16.542: App info: com.apple.Maps | Maps | system | arm64, x86_64 | Running | Not Debuggable | pid=73416
|
73
|
-
|
74
|
-
12:48:20.195: Tap: {
|
75
|
-
"x": 53,
|
76
|
-
"y": 749
|
77
|
-
}
|
78
|
-
|
79
|
-
12:48:20.404: Swipe (0.5s): {
|
80
|
-
"x": 196,
|
81
|
-
"y": 426
|
82
|
-
} => {
|
83
|
-
"x": 143,
|
84
|
-
"y": 447
|
85
|
-
}
|
86
|
-
|
87
|
-
12:48:21.155: Press (1.2s): {
|
88
|
-
"x": 143,
|
89
|
-
"y": 323
|
90
|
-
}
|
91
|
+
xcmonkey repeat --session-path "./xcmonkey-session.json"
|
91
92
|
```
|
92
93
|
|
93
94
|
### To describe the required point
|
94
95
|
|
95
96
|
```bash
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
20:05:21.713: x:20 y:625 point info: {
|
100
|
-
"AXFrame": "{{19, 624.3}, {86, 130.6}}",
|
101
|
-
"AXUniqueId": "ShortcutsRowCell",
|
102
|
-
"frame": {
|
103
|
-
"y": 624.3,
|
104
|
-
"x": 19,
|
105
|
-
"width": 86,
|
106
|
-
"height": 130.6
|
107
|
-
},
|
108
|
-
"role_description": "button",
|
109
|
-
"AXLabel": "Home",
|
110
|
-
"content_required": false,
|
111
|
-
"type": "Button",
|
112
|
-
"title": null,
|
113
|
-
"help": null,
|
114
|
-
"custom_actions": [
|
97
|
+
xcmonkey describe -x 20 -y 625 --udid "413EA256-CFFB-4312-94A6-12592BEE4CBA"
|
98
|
+
```
|
115
99
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
100
|
+
## [fastlane](https://github.com/fastlane/fastlane) integration
|
101
|
+
|
102
|
+
To run *xcmonkey* from *fastlane*, add the following code to your `Fastfile`:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
require 'xcmonkey'
|
106
|
+
|
107
|
+
lane :test do
|
108
|
+
Xcmonkey.new(
|
109
|
+
udid: '413EA256-CFFB-4312-94A6-12592BEE4CBA',
|
110
|
+
bundle_id: 'com.apple.Maps',
|
111
|
+
duration: 100
|
112
|
+
).run
|
113
|
+
end
|
122
114
|
```
|
123
115
|
|
124
116
|
## Code of Conduct
|
data/bin/xcmonkey
CHANGED
@@ -8,7 +8,7 @@ require_relative '../lib/xcmonkey/logger'
|
|
8
8
|
require_relative '../lib/xcmonkey/driver'
|
9
9
|
require_relative '../lib/xcmonkey/version'
|
10
10
|
|
11
|
-
|
11
|
+
class Xcmonkey
|
12
12
|
program :version, VERSION
|
13
13
|
program :description, 'xcmonkey is a tool for doing randomised UI testing of iOS apps'
|
14
14
|
|
@@ -21,11 +21,6 @@ module Xcmonkey
|
|
21
21
|
c.option('-k', '--enable-simulator-keyboard', 'Should simulator keyboard be enabled? Defaults to `true`')
|
22
22
|
c.option('-s', '--session-path STRING', String, 'Path where monkey testing session should be saved. Defaults to current directory')
|
23
23
|
c.action do |_, options|
|
24
|
-
options.default(
|
25
|
-
duration: 60,
|
26
|
-
session_path: Dir.pwd,
|
27
|
-
enable_simulator_keyboard: true
|
28
|
-
)
|
29
24
|
params = {
|
30
25
|
udid: options.udid,
|
31
26
|
bundle_id: options.bundle_id,
|
data/lib/xcmonkey/describer.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
class Describer
|
2
|
-
|
2
|
+
attr_accessor :x, :y, :driver
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
def initialize(params)
|
5
|
+
ensure_required_params(params)
|
6
|
+
self.x = params[:x]
|
7
|
+
self.y = params[:y]
|
8
|
+
self.driver = Driver.new(params)
|
9
|
+
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def run
|
12
|
+
driver.ensure_device_exists
|
13
|
+
driver.describe_point(x, y)
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def ensure_required_params(params)
|
17
|
+
Logger.error('UDID should be provided') if params[:udid].nil?
|
18
|
+
Logger.error('`x` point coordinate should be provided') if params[:x].nil? || params[:x].to_i.to_s != params[:x].to_s
|
19
|
+
Logger.error('`y` point coordinate should be provided') if params[:y].nil? || params[:y].to_i.to_s != params[:y].to_s
|
20
|
+
end
|
21
21
|
end
|
data/lib/xcmonkey/driver.rb
CHANGED
@@ -13,6 +13,7 @@ class Driver
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def monkey_test_precondition
|
16
|
+
puts
|
16
17
|
ensure_device_exists
|
17
18
|
ensure_app_installed
|
18
19
|
terminate_app
|
@@ -74,6 +75,8 @@ class Driver
|
|
74
75
|
end_coordinates: { x: action['endX'], y: action['endY'] },
|
75
76
|
duration: action['duration']
|
76
77
|
)
|
78
|
+
else
|
79
|
+
next
|
77
80
|
end
|
78
81
|
Logger.error('App lost') if describe_ui.shuffle.include?(@home_tracker)
|
79
82
|
end
|
@@ -119,33 +122,31 @@ class Driver
|
|
119
122
|
end
|
120
123
|
|
121
124
|
def list_targets
|
122
|
-
@
|
123
|
-
@
|
125
|
+
@targets ||= `idb list-targets --json`.split("\n").map! { |target| JSON.parse(target) }
|
126
|
+
@targets
|
124
127
|
end
|
125
128
|
|
126
|
-
def
|
127
|
-
`idb list-
|
129
|
+
def list_apps
|
130
|
+
`idb list-apps --udid #{udid} --json`.split("\n").map! { |app| JSON.parse(app) }
|
128
131
|
end
|
129
132
|
|
130
133
|
def ensure_app_installed
|
131
|
-
|
134
|
+
return if list_apps.any? { |app| app['bundle_id'] == bundle_id }
|
135
|
+
|
136
|
+
Logger.error("App #{bundle_id} is not installed on device #{udid}")
|
132
137
|
end
|
133
138
|
|
134
139
|
def ensure_device_exists
|
135
|
-
device = list_targets.detect { |target| target
|
140
|
+
device = list_targets.detect { |target| target['udid'] == udid }
|
136
141
|
Logger.error("Can't find device #{udid}") if device.nil?
|
137
142
|
|
138
|
-
Logger.info('Device info:', payload: device)
|
139
|
-
if device
|
143
|
+
Logger.info('Device info:', payload: JSON.pretty_generate(device))
|
144
|
+
if device['type'] == 'simulator'
|
140
145
|
configure_simulator_keyboard
|
141
146
|
boot_simulator
|
142
147
|
end
|
143
148
|
end
|
144
149
|
|
145
|
-
def list_apps
|
146
|
-
`idb list-apps --udid #{udid}`
|
147
|
-
end
|
148
|
-
|
149
150
|
def tap(coordinates:)
|
150
151
|
Logger.info('Tap:', payload: JSON.pretty_generate(coordinates))
|
151
152
|
@session[:actions] << { type: :tap, x: coordinates[:x], y: coordinates[:y] } unless session_actions
|
@@ -234,14 +235,13 @@ class Driver
|
|
234
235
|
end
|
235
236
|
|
236
237
|
def wait_until_app_launched
|
237
|
-
|
238
|
+
app_is_running = false
|
238
239
|
current_time = Time.now
|
239
|
-
while
|
240
|
-
app_info = list_apps.
|
241
|
-
|
242
|
-
end
|
240
|
+
while !app_is_running && Time.now < current_time + 5
|
241
|
+
app_info = list_apps.detect { |app| app['bundle_id'] == bundle_id }
|
242
|
+
app_is_running = app_info && app_info['process_state'] == 'Running'
|
243
243
|
end
|
244
|
-
Logger.error("Can't run the app #{bundle_id}")
|
245
|
-
Logger.info('App info:', payload: app_info)
|
244
|
+
Logger.error("Can't run the app #{bundle_id}") unless app_is_running
|
245
|
+
Logger.info('App info:', payload: JSON.pretty_generate(app_info))
|
246
246
|
end
|
247
247
|
end
|
data/lib/xcmonkey/repeater.rb
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
class Repeater
|
2
|
-
|
2
|
+
attr_accessor :udid, :bundle_id, :enable_simulator_keyboard, :actions
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
def initialize(params)
|
5
|
+
validate_session(params[:session_path])
|
6
|
+
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
def run
|
9
|
+
params = {
|
10
|
+
udid: udid,
|
11
|
+
bundle_id: bundle_id,
|
12
|
+
enable_simulator_keyboard: enable_simulator_keyboard,
|
13
|
+
session_actions: actions
|
14
|
+
}
|
15
|
+
Driver.new(params).repeat_monkey_test
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
def validate_session(session_path)
|
19
|
+
Logger.error("Provided session can't be found: #{session_path}") unless File.exist?(session_path)
|
20
20
|
|
21
|
-
|
21
|
+
session = JSON.parse(File.read(session_path))
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
if session['params'].nil?
|
24
|
+
Logger.error('Provided session is not valid: `params` should not be `nil`')
|
25
|
+
return
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
self.actions = session['actions']
|
29
|
+
Logger.error('Provided session is not valid: `actions` should not be `nil` or `empty`') if actions.nil? || actions.empty?
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
self.udid = session['params']['udid']
|
32
|
+
Logger.error('Provided session is not valid: `udid` should not be `nil`') if udid.nil?
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
self.bundle_id = session['params']['bundle_id']
|
35
|
+
Logger.error('Provided session is not valid: `bundle_id` should not be `nil`') if bundle_id.nil?
|
36
36
|
|
37
|
-
|
38
|
-
|
37
|
+
self.enable_simulator_keyboard = session['params']['enable_simulator_keyboard']
|
38
|
+
end
|
39
39
|
end
|
data/lib/xcmonkey/version.rb
CHANGED
data/lib/xcmonkey.rb
CHANGED
@@ -6,36 +6,37 @@ require_relative 'xcmonkey/version'
|
|
6
6
|
require_relative 'xcmonkey/logger'
|
7
7
|
require_relative 'xcmonkey/driver'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
attr_accessor :driver
|
9
|
+
class Xcmonkey
|
10
|
+
attr_accessor :driver
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def initialize(params)
|
13
|
+
params[:session_path] = Dir.pwd if params[:session_path].nil?
|
14
|
+
params[:duration] = 60 if params[:duration].nil?
|
15
|
+
params[:enable_simulator_keyboard] = true if params[:enable_simulator_keyboard].nil?
|
16
|
+
ensure_required_params(params)
|
17
|
+
self.driver = Driver.new(params)
|
18
|
+
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
def run
|
21
|
+
driver.monkey_test(gestures)
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def gestures
|
25
|
+
taps = [:precise_tap, :blind_tap] * 10
|
26
|
+
swipes = [:precise_swipe, :blind_swipe] * 5
|
27
|
+
presses = [:precise_press, :blind_press]
|
28
|
+
taps + swipes + presses
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
+
def ensure_required_params(params)
|
32
|
+
Logger.error('UDID should be provided') if params[:udid].nil?
|
31
33
|
|
32
|
-
|
34
|
+
Logger.error('Bundle identifier should be provided') if params[:bundle_id].nil?
|
33
35
|
|
34
|
-
|
36
|
+
Logger.error('Session path should be a directory') if params[:session_path].nil? || !File.directory?(params[:session_path])
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
38
|
+
if params[:duration].nil? || !params[:duration].kind_of?(Integer) || !params[:duration].positive?
|
39
|
+
Logger.error('Duration must be Integer and not less than 1 second')
|
40
|
+
end
|
41
|
+
end
|
41
42
|
end
|
data/spec/driver_spec.rb
CHANGED
@@ -10,12 +10,6 @@ describe Driver do
|
|
10
10
|
expect { driver.boot_simulator }.not_to raise_error
|
11
11
|
end
|
12
12
|
|
13
|
-
it 'verifies that there are booted simulators' do
|
14
|
-
driver.boot_simulator
|
15
|
-
booted_simulators = driver.list_booted_simulators
|
16
|
-
expect(booted_simulators).not_to be_empty
|
17
|
-
end
|
18
|
-
|
19
13
|
it 'verifies that ui can be described' do
|
20
14
|
driver.boot_simulator
|
21
15
|
ui = driver.describe_ui
|
@@ -41,8 +35,8 @@ describe Driver do
|
|
41
35
|
|
42
36
|
it 'verifies that list of apps can be showed' do
|
43
37
|
driver.boot_simulator
|
44
|
-
|
45
|
-
expect(
|
38
|
+
app_exists = driver.list_apps.any? { |app| app['bundle_id'] == bundle_id }
|
39
|
+
expect(app_exists).to be(true)
|
46
40
|
end
|
47
41
|
|
48
42
|
it 'verifies that app installed' do
|
@@ -62,11 +56,11 @@ describe Driver do
|
|
62
56
|
end
|
63
57
|
|
64
58
|
it 'verifies that device exists' do
|
65
|
-
|
66
|
-
|
67
|
-
expect(Logger).
|
68
|
-
expect(Logger).to receive(:info).with('Device info:', payload: payload)
|
59
|
+
payload = driver.list_targets.detect { |target| target['udid'] == udid }
|
60
|
+
expect(Logger).not_to receive(:error)
|
61
|
+
expect(Logger).to receive(:info).with('Device info:', payload: JSON.pretty_generate(payload))
|
69
62
|
expect(driver).to receive(:boot_simulator)
|
63
|
+
expect(driver).to receive(:configure_simulator_keyboard)
|
70
64
|
expect { driver.ensure_device_exists }.not_to raise_error
|
71
65
|
end
|
72
66
|
|
@@ -211,6 +205,48 @@ describe Driver do
|
|
211
205
|
driver.save_session
|
212
206
|
end
|
213
207
|
|
208
|
+
it 'verifies that monkey_test_precondition works fine' do
|
209
|
+
driver.monkey_test_precondition
|
210
|
+
app_info = driver.list_apps.detect { |app| app['bundle_id'] == bundle_id }
|
211
|
+
app_is_running = app_info && app_info['process_state'] == 'Running'
|
212
|
+
expect(app_is_running).to be(true)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'verifies that monkey_test works fine' do
|
216
|
+
params = { udid: udid, bundle_id: bundle_id, duration: 1, session_path: Dir.pwd }
|
217
|
+
driver = described_class.new(params)
|
218
|
+
expect(driver).to receive(:monkey_test_precondition)
|
219
|
+
driver.monkey_test(Xcmonkey.new(params).gestures)
|
220
|
+
expect(driver.instance_variable_get(:@session)[:actions]).not_to be_empty
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'verifies that repeat_monkey_test works fine' do
|
224
|
+
session_actions = [
|
225
|
+
{ 'type' => 'tap', 'x' => 10, 'y' => 10 },
|
226
|
+
{ 'type' => 'press', 'x' => 11, 'y' => 11, 'duration' => 1.4 },
|
227
|
+
{ 'type' => 'swipe', 'x' => 12, 'y' => 12, 'endX' => 15, 'endY' => 15, 'duration' => 0.3 }
|
228
|
+
]
|
229
|
+
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
|
+
expect(driver).to receive(:tap).with(coordinates: { x: 10, y: 10 })
|
233
|
+
expect(driver).to receive(:press).with(coordinates: { x: 11, y: 11 }, duration: 1.4)
|
234
|
+
expect(driver).to receive(:swipe).with(start_coordinates: { x: 12, y: 12 }, end_coordinates: { x: 15, y: 15 }, duration: 0.3)
|
235
|
+
driver.repeat_monkey_test
|
236
|
+
expect(driver.instance_variable_get(:@session)[:actions]).to be_empty
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'verifies that unknown actions does not break repeat_monkey_test' do
|
240
|
+
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
|
+
expect(driver).to receive(:monkey_test_precondition)
|
243
|
+
expect(driver).not_to receive(:tap)
|
244
|
+
expect(driver).not_to receive(:press)
|
245
|
+
expect(driver).not_to receive(:swipe)
|
246
|
+
driver.repeat_monkey_test
|
247
|
+
expect(driver.instance_variable_get(:@session)[:actions]).to be_empty
|
248
|
+
end
|
249
|
+
|
214
250
|
it 'verifies that simulator was not booted' do
|
215
251
|
driver.shutdown_simulator
|
216
252
|
error_message = "Failed to boot #{udid}"
|
data/spec/repeater_spec.rb
CHANGED
@@ -7,7 +7,6 @@ describe Repeater do
|
|
7
7
|
let(:session_file_content_without_bundle_id) { '{ "params": {"udid": "0", "enable_simulator_keyboard": true}, "actions": [{ "type": "tap", "x": 0, "y": 0 }] }' }
|
8
8
|
let(:session_file_content_without_udid) { '{ "params": {"bundle_id": "0", "enable_simulator_keyboard": true}, "actions": [{ "type": "tap", "x": 0, "y": 0 }] }' }
|
9
9
|
|
10
|
-
# TESTME
|
11
10
|
it 'verifies that session cannot be validated without params' do
|
12
11
|
allow(File).to receive(:exist?).and_return(true)
|
13
12
|
allow(File).to receive(:read).and_return(session_file_content_without_params)
|
data/spec/xcmonkey_spec.rb
CHANGED
@@ -1,58 +1,52 @@
|
|
1
1
|
describe Xcmonkey do
|
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
|
-
expect(current_version).to be > Gem::Version.new('0.1.0')
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'verifies gem name' do
|
55
|
-
expect(Xcmonkey::GEM_NAME).to eq('xcmonkey')
|
56
|
-
end
|
2
|
+
let(:params) { { udid: '123', bundle_id: 'example.com.app', duration: 10, session_path: Dir.pwd } }
|
3
|
+
let(:duration_error_msg) { 'Duration must be Integer and not less than 1 second' }
|
4
|
+
|
5
|
+
it 'verifies gestures' do
|
6
|
+
gestures = described_class.new(params).gestures
|
7
|
+
taps = [:precise_tap, :blind_tap] * 10
|
8
|
+
swipes = [:precise_swipe, :blind_swipe] * 5
|
9
|
+
presses = [:precise_press, :blind_press]
|
10
|
+
expect(gestures) =~ presses + taps + swipes
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'verifies required params' do
|
14
|
+
expect(Logger).not_to receive(:error)
|
15
|
+
described_class.new(params)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'verifies `udid` param is required' do
|
19
|
+
params[:udid] = nil
|
20
|
+
expect(Logger).to receive(:error).with('UDID should be provided')
|
21
|
+
described_class.new(params)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'verifies `bundle_id` param is required' do
|
25
|
+
params[:bundle_id] = nil
|
26
|
+
expect(Logger).to receive(:error).with('Bundle identifier should be provided')
|
27
|
+
described_class.new(params)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'verifies `duration` param is optional' do
|
31
|
+
params[:duration] = nil
|
32
|
+
expect(Logger).not_to receive(:error)
|
33
|
+
described_class.new(params)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'verifies `duration` param cannot be equal to zero' do
|
37
|
+
params[:duration] = 0
|
38
|
+
expect(Logger).to receive(:error).with(duration_error_msg)
|
39
|
+
described_class.new(params)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'verifies `duration` param cannot be negative' do
|
43
|
+
params[:duration] = -1
|
44
|
+
expect(Logger).to receive(:error).with(duration_error_msg)
|
45
|
+
described_class.new(params)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'verifies version' do
|
49
|
+
current_version = Gem::Version.new(Xcmonkey::VERSION)
|
50
|
+
expect(current_version).to be > Gem::Version.new('0.1.0')
|
57
51
|
end
|
58
52
|
end
|
data/xcmonkey.gemspec
CHANGED
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
3
|
require "xcmonkey/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
6
|
+
spec.name = "xcmonkey"
|
7
7
|
spec.version = Xcmonkey::VERSION
|
8
8
|
spec.authors = ["alteral"]
|
9
9
|
spec.email = ["a.alterpesotskiy@mail.ru"]
|
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.1.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-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -216,9 +216,9 @@ extra_rdoc_files: []
|
|
216
216
|
files:
|
217
217
|
- ".fasterer.yml"
|
218
218
|
- ".github/FUNDING.yml"
|
219
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
220
|
+
- ".github/ISSUE_TEMPLATE/feature-request.md"
|
219
221
|
- ".github/dependabot.yml"
|
220
|
-
- ".github/issue_template/bug_report.md"
|
221
|
-
- ".github/issue_template/feature_request.md"
|
222
222
|
- ".github/pull_request_template.md"
|
223
223
|
- ".github/workflows/test.yml"
|
224
224
|
- ".gitignore"
|