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
@@ -2,156 +2,151 @@ require 'kraken-mobile/models/device'
2
2
  require 'kraken-mobile/constants'
3
3
 
4
4
  module KrakenMobile
5
- module DevicesHelper
6
- class AdbHelper
7
- # ADB command that returns all phones and emulators connected to the computer.
8
- def adb_devices_l
9
- `adb devices -l`
10
- end
11
-
12
- def file_content file_name, device_id
5
+ module DevicesHelper
6
+ class AdbHelper
7
+ # ADB command that returns all phones and
8
+ # emulators connected to the computer.
9
+
10
+ def adb_devices_l
11
+ `adb devices -l`
12
+ end
13
+
14
+ def file_content(file_name, device_id)
13
15
  `adb -s #{device_id} shell "cat /sdcard/#{file_name} 2> /dev/null"`
14
16
  end
15
17
 
16
- def write_content_to_device content, file_name, device_id
18
+ def write_content_to_device(content, file_name, device_id)
17
19
  `adb -s #{device_id} shell "echo "#{content}" > /sdcard/#{file_name}"`
18
20
  end
19
21
 
20
- def create_file_in_device file_name, device_id
22
+ def create_file_in_device(file_name, device_id)
21
23
  `adb -s #{device_id} shell "> /sdcard/#{file_name}"`
22
24
  end
23
25
 
24
- def delete_file_in_device file_name, device_id
26
+ def delete_file_in_device(file_name, device_id)
25
27
  `adb -s #{device_id} shell "rm -rf /sdcard/#{file_name}"`
26
28
  end
27
29
 
28
- def device_screen_size device_id
30
+ def device_screen_size(device_id)
29
31
  `adb -s #{device_id} shell wm size`
30
32
  end
31
33
 
32
- def device_sdk_version device_id
34
+ def device_sdk_version(device_id)
33
35
  `adb -s #{device_id} shell getprop ro.build.version.sdk`
34
36
  end
35
37
 
36
- def device_orientation device_id
38
+ def device_orientation(device_id)
37
39
  `adb -s #{device_id} shell dumpsys input | grep 'SurfaceOrientation' | awk '{ print $2 }'`
38
40
  end
39
41
 
40
- def is_device_connected device_id
41
- begin
42
- adb_devices_l.include?(device_id)
43
- rescue
44
- false
42
+ def device_connected?(device_id)
43
+ adb_devices_l.include?(device_id)
44
+ rescue StandardError => _e
45
+ false
46
+ end
47
+
48
+ # Returns an array with all the devices and emulators
49
+ # connected to the computer.
50
+ def connected_devices
51
+ devices = []
52
+ adb_devices_l.split("\n").each do |line|
53
+ line_id = extract_device_id(line)
54
+ line_model = extract_device_model(line)
55
+ if line_id && line_model
56
+ device = Models::Device.new(line_id, line_model, devices.size + 1)
57
+ devices << device
58
+ end
45
59
  end
60
+ devices
61
+ rescue StandardError => _e
62
+ []
46
63
  end
47
64
 
48
- # Returns an array with all the devices and emulators connected to the computer.
49
- def connected_devices
50
- begin
51
- devices = []
52
- list =
53
- adb_devices_l.split("\n").each do |line|
54
- line_id = extract_device_id(line)
55
- line_model = extract_device_model(line)
56
- if line_id && line_model
57
- device = Models::Device.new(line_id, line_model, devices.size + 1)
58
- devices << device
59
- end
60
- end
61
- devices
62
- rescue
63
- []
64
- end
65
- end
66
-
67
- def read_file_content file_name, device_id
68
- begin
69
- raise "Device #{device_id} not found" unless is_device_connected(device_id)
70
- content = file_content("#{file_name}.txt", device_id)
71
- content.strip
72
- rescue
73
- ""
65
+ def read_file_content(file_name, device_id)
66
+ unless device_connected?(device_id)
67
+ raise "Device #{device_id} not found"
74
68
  end
69
+
70
+ content = file_content("#{file_name}.txt", device_id)
71
+ content.strip
72
+ rescue StandardError => _e
73
+ ''
75
74
  end
76
75
 
77
- def write_content_to_file content, file_name, device_id
78
- begin
79
- raise "Device #{device_id} not found" unless is_device_connected(device_id)
80
- write_content_to_device(content, "#{file_name}.txt", device_id)
81
- true
82
- rescue
83
- false
76
+ def write_content_to_file(content, file_name, device_id)
77
+ unless device_connected?(device_id)
78
+ raise "Device #{device_id} not found"
84
79
  end
80
+
81
+ write_content_to_device(content, "#{file_name}.txt", device_id)
82
+ true
83
+ rescue StandardError => _e
84
+ false
85
85
  end
86
86
 
87
- def create_file file_name, device_id
88
- begin
89
- raise "Device #{device_id} not found" unless is_device_connected(device_id)
90
- create_file_in_device("#{file_name}.txt", device_id)
91
- true
92
- rescue
93
- false
87
+ def create_file(file_name, device_id)
88
+ unless device_connected?(device_id)
89
+ raise "Device #{device_id} not found"
94
90
  end
91
+
92
+ create_file_in_device("#{file_name}.txt", device_id)
93
+ true
94
+ rescue StandardError => _e
95
+ false
95
96
  end
96
97
 
97
- def delete_file file_name, device_id
98
- begin
99
- raise "Device #{device_id} not found" unless is_device_connected(device_id)
100
- delete_file_in_device("#{file_name}.txt", device_id)
101
- true
102
- rescue
103
- false
98
+ def delete_file(file_name, device_id)
99
+ unless device_connected?(device_id)
100
+ raise "Device #{device_id} not found"
104
101
  end
102
+
103
+ delete_file_in_device("#{file_name}.txt", device_id)
104
+ true
105
+ rescue StandardError => _e
106
+ false
105
107
  end
106
108
 
107
109
  # Returns height, width
108
- def screen_size device_id
109
- begin
110
- adb_size = device_screen_size device_id
111
- parts = adb_size.strip!.split(" ")
112
- size = parts[parts.count-1]
113
- return 0,0 if !size.include?("x")
114
- size_parts = size.split("x")
115
- if orientation(device_id) == KrakenMobile::Constants::PORTRAIT
116
- return size_parts[1].to_i, size_parts[0].to_i
117
- else
118
- return size_parts[0].to_i, size_parts[1].to_i
119
- end
120
- rescue
121
- return 0,0
110
+ def screen_size(device_id)
111
+ adb_size = device_screen_size device_id
112
+ parts = adb_size.strip!.split(' ')
113
+ size = parts[parts.count - 1]
114
+ return [0, 0] unless size.include?('x')
115
+
116
+ size_parts = size.split('x')
117
+ if orientation(device_id) == KrakenMobile::Constants::PORTRAIT
118
+ return size_parts[1].to_i, size_parts[0].to_i
122
119
  end
120
+
121
+ [size_parts[0].to_i, size_parts[1].to_i]
122
+ rescue StandardError => _e
123
+ [0, 0]
123
124
  end
124
125
 
125
- def sdk_version device_id
126
- begin
127
- return device_sdk_version device_id
128
- rescue
129
- return "N/A"
130
- end
126
+ def sdk_version(device_id)
127
+ device_sdk_version device_id
128
+ rescue StandardError => _e
129
+ 'N/A'
131
130
  end
132
131
 
133
- def orientation device_id
134
- begin
135
- adb_orientation = device_orientation(device_id).strip!
136
- return adb_orientation.to_i
137
- rescue
138
- return KrakenMobile::Constants::PORTRAIT
139
- end
132
+ def orientation(device_id)
133
+ adb_orientation = device_orientation(device_id).strip!
134
+ adb_orientation.to_i
135
+ rescue StandardError => _e
136
+ KrakenMobile::Constants::PORTRAIT
140
137
  end
141
138
 
142
139
  # Parses the device id from the ADB devices command.
143
- def extract_device_id line
144
- if line.match(/device(?!s)/)
145
- line.split(" ").first
146
- end
147
- end
140
+ def extract_device_id(line)
141
+ return line.split(' ').first if line.match(/device(?!s)/)
142
+ end
148
143
 
149
144
  # Parses the device model from the ADB devices command.
150
- def extract_device_model line
151
- if line.match(/device(?!s)/)
152
- line.scan(/model:(.*) device/).flatten.first
153
- end
154
- end
155
- end
156
- end
145
+ def extract_device_model(line)
146
+ return unless line.match(/device(?!s)/)
147
+
148
+ line.scan(/model:(.*) device/).flatten.first
149
+ end
150
+ end
151
+ end
157
152
  end
@@ -0,0 +1,108 @@
1
+ require 'faker'
2
+ require 'kraken-mobile/utils/k.rb'
3
+ require 'json'
4
+
5
+ class KrakenFaker
6
+ #-------------------------------
7
+ # Fields
8
+ #-------------------------------
9
+ attr_accessor :process_id
10
+
11
+ #-------------------------------
12
+ # Constructors
13
+ #-------------------------------
14
+ def initialize(process_id:)
15
+ raise 'ERROR: Can\'t create faker for null process id' if process_id.nil?
16
+
17
+ @process_id = process_id
18
+ end
19
+
20
+ #-------------------------------
21
+ # Helpers
22
+ #-------------------------------
23
+ def generate_value_for_key(key:)
24
+ value = if key.start_with?('$name')
25
+ generate_name
26
+ elsif key.start_with?('$number')
27
+ generate_number
28
+ elsif key.start_with?('$email')
29
+ generate_email
30
+ elsif key.start_with?('$string')
31
+ generate_string
32
+ elsif key.start_with?('$date')
33
+ generate_date
34
+ else
35
+ raise 'ERROR: Faker key not supported'
36
+ end
37
+ save_key_value_in_dictionary(key: key, value: value)
38
+ value
39
+ end
40
+
41
+ def reuse_value_for_key(key:)
42
+ dictionary = dictionary_json
43
+ key = key.delete_prefix('$')
44
+
45
+ raise 'ERROR: Key does not exist' if dictionary[process_id.to_s].nil?
46
+ if dictionary[process_id.to_s][key.to_s].nil?
47
+ raise 'ERROR: Key does not exist'
48
+ end
49
+
50
+ dictionary[process_id.to_s][key.to_s]
51
+ end
52
+
53
+ def dictionary_json
54
+ create_dictionary_json_file unless dictionary_json_file_exists?
55
+
56
+ absolute_dictionary_path = File.expand_path(K::DICTIONARY_PATH)
57
+ file = open(absolute_dictionary_path)
58
+ content = file.read
59
+ file.close
60
+ JSON.parse(content)
61
+ end
62
+
63
+ def create_dictionary_json_file
64
+ absolute_dictionary_path = File.expand_path(K::DICTIONARY_PATH)
65
+ File.open(absolute_dictionary_path, 'w') do |f|
66
+ f.puts({}.to_json)
67
+ end
68
+ end
69
+
70
+ def dictionary_json_file_exists?
71
+ absolute_dictionary_path = File.expand_path(K::DICTIONARY_PATH)
72
+ File.file?(absolute_dictionary_path)
73
+ end
74
+
75
+ def save_key_value_in_dictionary(key:, value:)
76
+ current_json = dictionary_json
77
+ current_json[process_id.to_s] = {} if current_json[process_id.to_s].nil?
78
+ current_json[process_id.to_s][key.to_s] = value
79
+
80
+ absolute_dictionary_path = File.expand_path(K::DICTIONARY_PATH)
81
+ open(absolute_dictionary_path, 'w') do |f|
82
+ f.puts(current_json.to_json)
83
+ end
84
+ end
85
+
86
+ #-------------------------------
87
+ # Generators
88
+ #-------------------------------
89
+ def generate_name
90
+ Faker::Name.first_name
91
+ end
92
+
93
+ def generate_number
94
+ Faker::Number.number(digits: rand(10))
95
+ end
96
+
97
+ def generate_email
98
+ Faker::Internet.email
99
+ end
100
+
101
+ def generate_string
102
+ Faker::String.random(length: rand(100))
103
+ end
104
+
105
+ def generate_date
106
+ Faker::Date.in_date_period.to_s
107
+ end
108
+ end
@@ -26,6 +26,7 @@ module KrakenMobile
26
26
  # Variables
27
27
  report_file = open("#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{KrakenMobile::Constants::REPORT_DEVICES_FILE_NAME}.json")
28
28
  content = report_file.read
29
+ report_file.close
29
30
  @devices = JSON.parse(content)
30
31
  devices_report = report_by_devices(@devices)
31
32
  @features_report = fetures_from_report_by_devices devices_report
@@ -45,6 +46,7 @@ module KrakenMobile
45
46
  @apk_path = device.config["apk_path"] ? device.config["apk_path"] : @options[:apk_path]
46
47
  report_file = open("#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{device.id}/#{KrakenMobile::Constants::REPORT_FILE_NAME}.json")
47
48
  content = report_file.read
49
+ report_file.close
48
50
  @features = JSON.parse(content)
49
51
  @total_scenarios = total_scenarios @features
50
52
  @device = device
@@ -70,6 +72,7 @@ module KrakenMobile
70
72
  next if !File.exists?("#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{device['id']}/#{KrakenMobile::Constants::REPORT_FILE_NAME}.json")
71
73
  report_file = open("#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{device['id']}/#{KrakenMobile::Constants::REPORT_FILE_NAME}.json")
72
74
  content = report_file.read
75
+ report_file.close
73
76
  devices_report[device['user']] = JSON.parse(content)
74
77
  devices_report[device['user']].each do |d| d["device_model"] = device["model"] if !d["device_model"] end
75
78
  devices_report[device['user']].each do |d| d["device_id"] = device["id"] if !d["device_id"] end
@@ -0,0 +1,15 @@
1
+ require 'calabash-android/management/adb'
2
+ require 'calabash-android/operations'
3
+
4
+ Before do |scenario|
5
+ # install_app_with_calabash
6
+ @scenario_tags = scenario.source_tag_names
7
+ end
8
+
9
+ After do |scenario|
10
+ @scenario_tags = scenario.source_tag_names
11
+ end
12
+
13
+ AfterStep do |_scenario|
14
+ screenshot_embed
15
+ end
@@ -0,0 +1,36 @@
1
+ require 'calabash-android/management/adb'
2
+ require 'calabash-android/operations'
3
+ require 'kraken-mobile/test_scenario'
4
+
5
+ def start_test_kraken_server_in_background
6
+ start_test_server_in_background
7
+
8
+ DeviceProcess.notify_process_state(
9
+ process_id: process_id,
10
+ state: K::PROCESS_STATES[:ready_to_start]
11
+ )
12
+
13
+ Timeout.timeout(K::DEFAULT_START_TIMEOUT_SECONDS, RuntimeError) do
14
+ sleep(1) until TestScenario.ready_to_start?
15
+ end
16
+ end
17
+
18
+ def shutdown_test_kraken_server
19
+ DeviceProcess.notify_process_state(
20
+ process_id: process_id,
21
+ state: K::PROCESS_STATES[:ready_to_finish]
22
+ )
23
+
24
+ Timeout.timeout(K::DEFAULT_FINISH_TIMEOUT_SECONDS, RuntimeError) do
25
+ sleep(1) until TestScenario.ready_to_finish?
26
+ end
27
+
28
+ shutdown_test_server
29
+ end
30
+
31
+ private
32
+
33
+ def process_id
34
+ tag_process_id = @scenario_tags.grep(/@user/).first
35
+ tag_process_id.delete_prefix('@user')
36
+ end
@@ -0,0 +1,33 @@
1
+ require 'kraken-mobile/test_scenario'
2
+
3
+ def start_test_kraken_server_in_background(scenario:)
4
+ @scenario_tags = scenario.source_tag_names
5
+ DeviceProcess.notify_process_state(
6
+ process_id: process_id(scenario: scenario),
7
+ state: K::PROCESS_STATES[:ready_to_start]
8
+ )
9
+
10
+ Timeout.timeout(K::DEFAULT_START_TIMEOUT_SECONDS, RuntimeError) do
11
+ sleep(1) until TestScenario.ready_to_start?
12
+ end
13
+ end
14
+
15
+ def shutdown_test_kraken_server(scenario:)
16
+ @scenario_tags = scenario.source_tag_names
17
+ DeviceProcess.notify_process_state(
18
+ process_id: process_id(scenario: scenario),
19
+ state: K::PROCESS_STATES[:ready_to_finish]
20
+ )
21
+
22
+ Timeout.timeout(K::DEFAULT_FINISH_TIMEOUT_SECONDS, RuntimeError) do
23
+ sleep(1) until TestScenario.ready_to_finish?
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def process_id(scenario:)
30
+ scenario_tags = scenario.source_tag_names
31
+ tag_process_id = scenario_tags.grep(/@user/).first
32
+ tag_process_id.delete_prefix('@user')
33
+ end