kraken-mobile 1.0.2 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +251 -75
  3. data/bin/kraken-mobile +64 -67
  4. data/bin/kraken_mobile_calabash_android.rb +39 -0
  5. data/bin/kraken_mobile_helpers.rb +107 -0
  6. data/bin/kraken_mobile_setup.rb +138 -0
  7. data/calabash-android-features-skeleton/step_definitions/mobile_steps.rb +1 -0
  8. data/calabash-android-features-skeleton/support/app_installation_hooks.rb +2 -0
  9. data/calabash-android-features-skeleton/support/app_life_cycle_hooks.rb +3 -4
  10. data/calabash-android-features-skeleton/support/env.rb +1 -1
  11. data/calabash-android-features-skeleton/web/step_definitions/web_steps.rb +3 -0
  12. data/calabash-android-features-skeleton/web/support/app_life_cycle_hooks.rb +15 -0
  13. data/lib/kraken-mobile/device_process.rb +130 -0
  14. data/lib/kraken-mobile/helpers/devices_helper/adb_helper.rb +100 -105
  15. data/lib/kraken-mobile/helpers/kraken_faker.rb +108 -0
  16. data/lib/kraken-mobile/helpers/reporter.rb +3 -0
  17. data/lib/kraken-mobile/hooks/mobile_kraken_hooks.rb +15 -0
  18. data/lib/kraken-mobile/hooks/mobile_operations.rb +36 -0
  19. data/lib/kraken-mobile/hooks/web_operations.rb +33 -0
  20. data/lib/kraken-mobile/mobile/adb.rb +66 -0
  21. data/lib/kraken-mobile/mobile/android_commands.rb +43 -0
  22. data/lib/kraken-mobile/mobile/mobile_process.rb +101 -0
  23. data/lib/kraken-mobile/models/android_device.rb +121 -0
  24. data/lib/kraken-mobile/models/device.rb +113 -31
  25. data/lib/kraken-mobile/models/feature_file.rb +135 -0
  26. data/lib/kraken-mobile/models/feature_scenario.rb +24 -0
  27. data/lib/kraken-mobile/models/web_device.rb +89 -0
  28. data/lib/kraken-mobile/monkeys/mobile/android_monkey.rb +30 -0
  29. data/lib/kraken-mobile/monkeys/mobile/kraken_android_monkey.rb +54 -0
  30. data/lib/kraken-mobile/monkeys/web/web_monkey.rb +63 -0
  31. data/lib/kraken-mobile/runners/calabash/android/monkey_helper.rb +2 -2
  32. data/lib/kraken-mobile/runners/calabash/android/steps/communication_steps.rb +18 -2
  33. data/lib/kraken-mobile/runners/calabash/monkey/monkey_runner.rb +2 -2
  34. data/lib/kraken-mobile/steps/general_steps.rb +83 -0
  35. data/lib/kraken-mobile/steps/mobile/kraken_steps.rb +72 -0
  36. data/lib/kraken-mobile/steps/web/kraken_steps.rb +109 -0
  37. data/lib/kraken-mobile/test_scenario.rb +227 -0
  38. data/lib/kraken-mobile/utils/feature_reader.rb +17 -0
  39. data/lib/kraken-mobile/utils/k.rb +68 -0
  40. data/lib/kraken-mobile/utils/mobile_cucumber.rb +2 -0
  41. data/lib/kraken-mobile/utils/reporter.rb +500 -0
  42. data/lib/kraken-mobile/version.rb +2 -2
  43. data/lib/kraken-mobile/web/web_process.rb +41 -0
  44. data/lib/kraken_mobile.rb +81 -0
  45. data/reporter/assets/images/krakenThumbnail.jpg +0 -0
  46. data/reporter/feature_report.html.erb +5 -1
  47. data/reporter/index.html.erb +13 -7
  48. metadata +94 -13
  49. data/bin/kraken-mobile-calabash-android.rb +0 -85
  50. data/bin/kraken-mobile-generate.rb +0 -19
  51. data/bin/kraken-mobile-helpers.rb +0 -48
  52. data/bin/kraken-mobile-setup.rb +0 -50
  53. data/calabash-android-features-skeleton/step_definitions/kraken_steps.rb +0 -1
  54. data/lib/kraken-mobile.rb +0 -29
@@ -0,0 +1,66 @@
1
+ require 'kraken-mobile/models/android_device'
2
+ require 'kraken-mobile/constants'
3
+ require 'kraken-mobile/mobile/android_commands.rb'
4
+
5
+ class ADB
6
+ class << self
7
+ include Android::Commands
8
+
9
+ def connected_devices
10
+ devices = []
11
+ adb_devices_l.split("\n").each do |line|
12
+ id = extract_device_id(line)
13
+ model = extract_device_model(line)
14
+ next if id.nil? || model.nil?
15
+
16
+ devices << AndroidDevice.new(id: id, model: model)
17
+ end
18
+ devices
19
+ rescue StandardError => _e
20
+ raise 'ERROR: Can\'t read Android devices connected.'
21
+ end
22
+
23
+ def device_screen_size(device_id:)
24
+ adb_size = screen_size_for_device_with_id(device_id: device_id)
25
+ extract_device_screen_size_info(adb_size)
26
+ rescue StandardError => _e
27
+ raise "ERROR: Can\'t read Android device #{device_id} screen size."
28
+ end
29
+
30
+ def save_snapshot_for_device_with_id_in_file_path(device_id:, file_path:)
31
+ save_snapshot_for_device_with_id_in_path(
32
+ device_id: device_id,
33
+ file_path: file_path
34
+ )
35
+ rescue StandardError => _e
36
+ raise "ERROR: Can\'t save snapshot for device #{device_id}."
37
+ end
38
+
39
+ def device_sdk_version(device_id:)
40
+ version = sdk_version_for_device_with_id(device_id: device_id)
41
+ version.strip
42
+ rescue StandardError => _e
43
+ raise "ERROR: Can\'t get SDK version for device #{device_id}."
44
+ end
45
+
46
+ private
47
+
48
+ def extract_device_id(line)
49
+ return line.split(' ').first if line.match(/device(?!s)/)
50
+ end
51
+
52
+ def extract_device_model(line)
53
+ return unless line.match(/device(?!s)/)
54
+
55
+ line.scan(/model:(.*) device/).flatten.first
56
+ end
57
+
58
+ def extract_device_screen_size_info(line)
59
+ parts = line.strip!.split(' ')
60
+ size = parts[parts.count - 1]
61
+ return [0, 0] unless size.include?('x')
62
+
63
+ size.split('x').map(&:to_i)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,43 @@
1
+ module Android
2
+ module Commands
3
+ # List of connected devices/emulators
4
+ def adb_devices_l
5
+ `adb devices -l`
6
+ end
7
+
8
+ def file_content(device_id:, file_name:)
9
+ `adb -s #{device_id} shell "cat /sdcard/#{file_name} 2> /dev/null"`
10
+ end
11
+
12
+ def write_content_to_file_with_name_in_device(
13
+ content:, device_id:, file_name:
14
+ )
15
+ `adb -s #{device_id} shell "echo "#{content}" > /sdcard/#{file_name}"`
16
+ end
17
+
18
+ def create_file_with_name_in_device(device_id:, file_name:)
19
+ `adb -s #{device_id} shell "> /sdcard/#{file_name}"`
20
+ end
21
+
22
+ def delete_file_with_name_in_device(device_id:, file_name:)
23
+ `adb -s #{device_id} shell "rm -rf /sdcard/#{file_name}"`
24
+ end
25
+
26
+ def device_orientation(device_id:)
27
+ `adb -s #{device_id} shell dumpsys input | grep 'SurfaceOrientation' \
28
+ | awk '{ print $2 }'`
29
+ end
30
+
31
+ def screen_size_for_device_with_id(device_id:)
32
+ `adb -s #{device_id} shell wm size`
33
+ end
34
+
35
+ def save_snapshot_for_device_with_id_in_path(device_id:, file_path:)
36
+ `adb -s #{device_id} shell cat /sdcard/window_dump.xml > #{file_path}`
37
+ end
38
+
39
+ def sdk_version_for_device_with_id(device_id:)
40
+ `adb -s #{device_id} shell getprop ro.build.version.sdk`
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,101 @@
1
+ require 'kraken-mobile/device_process.rb'
2
+ require 'kraken-mobile/utils/k.rb'
3
+
4
+ class MobileProcess < DeviceProcess
5
+ #-------------------------------
6
+ # Required methods
7
+ #-------------------------------
8
+ def before_execute
9
+ register_process_to_directory
10
+ device.create_inbox
11
+ end
12
+
13
+ def after_execute
14
+ unregister_process_from_directory
15
+ device.delete_inbox
16
+ end
17
+
18
+ def execute
19
+ open(execution_command, 'r') do |output|
20
+ loop do
21
+ $stdout.print output.readline.to_s
22
+ $stdout.flush
23
+ end
24
+ end
25
+ $CHILD_STATUS.exitstatus
26
+ rescue EOFError
27
+ nil
28
+ end
29
+
30
+ #-------------------------------
31
+ # Methods
32
+ #-------------------------------
33
+
34
+ def apk_path
35
+ return config_apk_path if @test_scenario.requires_predefined_devices?
36
+
37
+ path = @test_scenario&.kraken_app&.apk_path
38
+ raise 'ERROR: Invalid APK file path' if path.nil?
39
+
40
+ path
41
+ end
42
+
43
+ private
44
+
45
+ def execution_command
46
+ "|#{environment_variables_command}#{terminal_command_separator}"\
47
+ "#{running_process_command}"
48
+ end
49
+
50
+ def running_process_command
51
+ feature_path = test_scenario.feature_file.file_path
52
+ raise 'ERROR: Invalid feature file path' if feature_path.nil?
53
+
54
+ process_apk_path = apk_path
55
+ raise 'ERROR: Invalid APK file path' if process_apk_path.nil?
56
+
57
+ "calabash-android run #{process_apk_path} \
58
+ #{feature_path} --tags @user#{id} \
59
+ --require features/support/env.rb \
60
+ --require features/support/app_installation_hooks.rb \
61
+ --require features/support/app_life_cycle_hooks.rb \
62
+ --require features/step_definitions/mobile_steps.rb \
63
+ --format pretty --format json -o \
64
+ #{K::REPORT_PATH}/#{@test_scenario.execution_id}/#{device.id}/#{K::FILE_REPORT_NAME}"
65
+ end
66
+
67
+ def environment_variables_command
68
+ variables = {
69
+ ADB_DEVICE_ARG: device.id
70
+ }
71
+ exporting_command_for_environment_variables(variables)
72
+ end
73
+
74
+ #-------------------------------
75
+ # Helpers
76
+ #-------------------------------
77
+
78
+ def config_json
79
+ config_absolute_path = File.expand_path(ENV[K::CONFIG_PATH])
80
+ file = open(config_absolute_path)
81
+ content = file.read
82
+ file.close
83
+ JSON.parse(content)[@id.to_s] || {}
84
+ end
85
+
86
+ def config_apk_path
87
+ device_config_json = config_json
88
+ return if device_config_json['config'].nil?
89
+ return if device_config_json['config']['apk_path'].nil?
90
+
91
+ absolute_config_apk_path = File.expand_path(
92
+ device_config_json['config']['apk_path']
93
+ )
94
+
95
+ raise 'ERROR: Invalid config apk path' unless File.file?(
96
+ absolute_config_apk_path
97
+ )
98
+
99
+ absolute_config_apk_path
100
+ end
101
+ end
@@ -0,0 +1,121 @@
1
+ require 'kraken-mobile/models/device'
2
+ require 'kraken-mobile/mobile/adb'
3
+ require 'kraken-mobile/monkeys/mobile/kraken_android_monkey'
4
+ require 'kraken-mobile/monkeys/mobile/android_monkey'
5
+
6
+ class AndroidDevice < Device
7
+ include KrakenAndroidMonkey
8
+ include AndroidMonkey
9
+
10
+ #-------------------------------
11
+ # Signaling
12
+ #-------------------------------
13
+ def create_inbox
14
+ raise 'ERROR: Device is disconnected.' unless connected?
15
+
16
+ ADB.create_file_with_name_in_device(
17
+ device_id: @id,
18
+ file_name: K::INBOX_FILE_NAME
19
+ )
20
+ end
21
+
22
+ def delete_inbox
23
+ raise 'ERROR: Device is disconnected.' unless connected?
24
+
25
+ ADB.delete_file_with_name_in_device(
26
+ device_id: @id,
27
+ file_name: K::INBOX_FILE_NAME
28
+ )
29
+ end
30
+
31
+ def write_signal(signal)
32
+ ADB.write_content_to_file_with_name_in_device(
33
+ content: signal,
34
+ device_id: @id,
35
+ file_name: K::INBOX_FILE_NAME
36
+ )
37
+ end
38
+
39
+ def read_signal(signal, timeout = K::DEFAULT_TIMEOUT_SECONDS)
40
+ Timeout.timeout(timeout, RuntimeError) do
41
+ sleep(1) until inbox_last_signal == signal
42
+ end
43
+ end
44
+
45
+ #-------------------------------
46
+ # More interface methods
47
+ #-------------------------------
48
+ def connected?
49
+ ADB.connected_devices.any? do |device|
50
+ device.id == @id
51
+ end
52
+ end
53
+
54
+ def orientation
55
+ ADB.device_orientation(
56
+ device_id: @id
57
+ ).strip!.to_i
58
+ rescue StandardError => _e
59
+ K::ANDROID_PORTRAIT
60
+ end
61
+
62
+ def screen_size
63
+ size = ADB.device_screen_size(device_id: @id)
64
+
65
+ height = orientation == K::ANDROID_PORTRAIT ? size[1] : size[0]
66
+ width = orientation == K::ANDROID_PORTRAIT ? size[0] : size[1]
67
+
68
+ [height, width]
69
+ end
70
+
71
+ def sdk_version
72
+ ADB.device_sdk_version(device_id: @id)
73
+ end
74
+
75
+ def type
76
+ K::ANDROID_DEVICE
77
+ end
78
+
79
+ def save_snapshot_in_file_path(file_path)
80
+ raise 'ERROR: Invalid snapshot file path' if file_path.nil?
81
+
82
+ absolute_path = File.expand_path(file_path)
83
+ raise 'ERROR: File already exists' if File.file?(absolute_path)
84
+
85
+ ADB.save_snapshot_for_device_with_id_in_file_path(
86
+ device_id: @id,
87
+ file_path: absolute_path
88
+ )
89
+ end
90
+
91
+ #-------------------------------
92
+ # Random testing
93
+ #-------------------------------
94
+ def run_monkey_with_number_of_events(number_of_events)
95
+ execute_monkey(number_of_events)
96
+ end
97
+
98
+ def run_kraken_monkey_with_number_of_events(number_of_events)
99
+ execute_kraken_monkey(number_of_events)
100
+ end
101
+
102
+ #-------------------------------
103
+ # Helprs
104
+ #-------------------------------
105
+ def calabash_default_device
106
+ operations_module = Calabash::Android::Operations
107
+ operations_module::Device.new(
108
+ operations_module,
109
+ ENV['ADB_DEVICE_ARG'],
110
+ ENV['TEST_SERVER_PORT'],
111
+ ENV['APP_PATH'],
112
+ ENV['TEST_APP_PATH']
113
+ )
114
+ end
115
+
116
+ private
117
+
118
+ def inbox_last_signal
119
+ ADB.file_content(device_id: @id, file_name: K::INBOX_FILE_NAME).strip
120
+ end
121
+ end
@@ -1,32 +1,114 @@
1
- module KrakenMobile
2
- module Models
3
- class Device
4
-
5
- #-------------------------------
6
- # Fields
7
- #-------------------------------
8
- attr_accessor :id
9
- attr_accessor :model
10
- attr_accessor :position
11
- attr_accessor :config
12
-
13
- #-------------------------------
14
- # Constructors
15
- #-------------------------------
16
- def initialize(id, model, position, config = {})
17
- @id = id
18
- @model = model
19
- @position = position
20
- @config = config
21
- end
22
-
23
- #-------------------------------
24
- # Helpers
25
- #-------------------------------
26
- def screenshot_prefix
27
- @id.gsub('.', '_').gsub(/:(.*)/, '').to_s + '_'
28
- end
29
-
30
- end
31
- end
1
+ require 'kraken-mobile/device_process'
2
+
3
+ class Device
4
+ #-------------------------------
5
+ # Fields
6
+ #-------------------------------
7
+ attr_accessor :id
8
+ attr_accessor :model
9
+
10
+ #-------------------------------
11
+ # Constructors
12
+ #-------------------------------
13
+ def initialize(id:, model:)
14
+ @id = id
15
+ @model = model
16
+ end
17
+
18
+ #-------------------------------
19
+ # Signaling
20
+ #-------------------------------
21
+ def create_inbox
22
+ raise 'ERROR: create_inbox not implemented.'
23
+ end
24
+
25
+ def delete_inbox
26
+ raise 'ERROR: delete_inbox not implemented.'
27
+ end
28
+
29
+ def write_signal(_signal)
30
+ raise 'ERROR: write_signal not implemented.'
31
+ end
32
+
33
+ def read_signal(_signal, _timeout = K::DEFAULT_TIMEOUT_SECONDS)
34
+ raise 'ERROR: read_signal not implemented.'
35
+ end
36
+
37
+ #-------------------------------
38
+ # Random testing
39
+ #-------------------------------
40
+ def run_monkey_with_number_of_events(_number_of_events)
41
+ raise 'ERROR: run_monkey_with_number_of_events not implemented.'
42
+ end
43
+
44
+ def run_kraken_monkey_with_number_of_events(_number_of_events)
45
+ raise 'ERROR: run_kraken_monkey_with_number_of_events not implemented.'
46
+ end
47
+
48
+ #-------------------------------
49
+ # More interface methods
50
+ #-------------------------------
51
+ def connected?
52
+ raise 'ERROR: connected? not implemented.'
53
+ end
54
+
55
+ def orientation
56
+ raise 'ERROR: orientation not implemented.'
57
+ end
58
+
59
+ def screen_size
60
+ raise 'ERROR: screen_size not implemented.'
61
+ end
62
+
63
+ def sdk_version
64
+ raise 'ERROR: sdk_version not implemented.'
65
+ end
66
+
67
+ def type
68
+ raise 'ERROR: Unsupported device'
69
+ end
70
+
71
+ def save_snapshot_in_path(_file_path)
72
+ raise 'ERROR: save_snapshot_in_path not implemented.'
73
+ end
74
+
75
+ #-------------------------------
76
+ # Helpers
77
+ #-------------------------------
78
+ def to_s
79
+ @id + K::SEPARATOR + @model + K::SEPARATOR + type
80
+ end
81
+
82
+ def screenshot_prefix
83
+ @id.gsub('.', '_').gsub(/:(.*)/, '').to_s + '_'
84
+ end
85
+
86
+ def self.find_by_process_id(id)
87
+ DeviceProcess.directory.each do |process_info|
88
+ info = process_info.strip.split(K::SEPARATOR)
89
+ process_id = info[0]
90
+ next unless process_id.to_s == id.to_s
91
+
92
+ return device_from_type(
93
+ id: info[1], model: info[2],
94
+ device_type: info[3]
95
+ )
96
+ end
97
+
98
+ nil
99
+ end
100
+
101
+ def self.device_from_type(id:, model:, device_type:)
102
+ device_class = nil
103
+ if device_type == K::ANDROID_DEVICE
104
+ device_class = AndroidDevice
105
+ elsif device_type == K::WEB_DEVICE
106
+ device_class = WebDevice
107
+ end
108
+ raise 'ERROR: Unsupported device' if device_class.nil?
109
+
110
+ device_class.new(
111
+ id: id, model: model
112
+ )
113
+ end
32
114
  end