kraken-mobile 1.0.4 → 1.0.5

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -11
  3. data/bin/kraken-mobile +55 -67
  4. data/bin/kraken_mobile_calabash_android.rb +39 -0
  5. data/bin/kraken_mobile_helpers.rb +91 -0
  6. data/bin/kraken_mobile_setup.rb +134 -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 +94 -0
  14. data/lib/kraken-mobile/helpers/devices_helper/adb_helper.rb +100 -105
  15. data/lib/kraken-mobile/helpers/kraken_faker.rb +107 -0
  16. data/lib/kraken-mobile/hooks/mobile_kraken_hooks.rb +15 -0
  17. data/lib/kraken-mobile/hooks/mobile_operations.rb +36 -0
  18. data/lib/kraken-mobile/hooks/web_operations.rb +33 -0
  19. data/lib/kraken-mobile/mobile/adb.rb +66 -0
  20. data/lib/kraken-mobile/mobile/android_commands.rb +43 -0
  21. data/lib/kraken-mobile/mobile/mobile_process.rb +82 -0
  22. data/lib/kraken-mobile/models/android_device.rb +121 -0
  23. data/lib/kraken-mobile/models/device.rb +113 -31
  24. data/lib/kraken-mobile/models/feature_file.rb +108 -0
  25. data/lib/kraken-mobile/models/feature_scenario.rb +24 -0
  26. data/lib/kraken-mobile/models/web_device.rb +86 -0
  27. data/lib/kraken-mobile/monkeys/mobile/android_monkey.rb +30 -0
  28. data/lib/kraken-mobile/monkeys/mobile/kraken_android_monkey.rb +54 -0
  29. data/lib/kraken-mobile/runners/calabash/android/steps/communication_steps.rb +15 -0
  30. data/lib/kraken-mobile/steps/general_steps.rb +82 -0
  31. data/lib/kraken-mobile/steps/mobile/kraken_steps.rb +72 -0
  32. data/lib/kraken-mobile/steps/web/kraken_steps.rb +81 -0
  33. data/lib/kraken-mobile/test_scenario.rb +193 -0
  34. data/lib/kraken-mobile/utils/feature_reader.rb +17 -0
  35. data/lib/kraken-mobile/utils/k.rb +67 -0
  36. data/lib/kraken-mobile/utils/mobile_cucumber.rb +2 -0
  37. data/lib/kraken-mobile/utils/reporter.rb +453 -0
  38. data/lib/kraken-mobile/version.rb +2 -2
  39. data/lib/kraken-mobile/web/web_process.rb +39 -0
  40. data/lib/kraken_mobile.rb +77 -0
  41. data/reporter/index.html.erb +6 -6
  42. metadata +89 -9
  43. data/bin/kraken-mobile-calabash-android.rb +0 -85
  44. data/bin/kraken-mobile-generate.rb +0 -19
  45. data/bin/kraken-mobile-helpers.rb +0 -48
  46. data/bin/kraken-mobile-setup.rb +0 -50
  47. data/calabash-android-features-skeleton/step_definitions/kraken_steps.rb +0 -1
  48. data/lib/kraken-mobile.rb +0 -29
@@ -0,0 +1 @@
1
+ require 'kraken-mobile/steps/mobile/kraken_steps'
@@ -14,6 +14,8 @@ Before do |scenario|
14
14
  else
15
15
  log 'First scenario in feature - reinstalling apps'
16
16
  end
17
+
18
+ ensure_app_installed
17
19
  clear_app_data
18
20
  FeatureMemory.feature = feature
19
21
  FeatureMemory.invocation = 1
@@ -1,10 +1,9 @@
1
- require 'kraken-mobile/runners/calabash/android/operations'
1
+ require 'kraken-mobile/hooks/mobile_operations'
2
2
 
3
3
  Before do |scenario|
4
- start_kraken_test_server_in_background scenario
4
+ start_test_kraken_server_in_background
5
5
  end
6
6
 
7
7
  After do |scenario|
8
- shutdown_kraken_test_server scenario
9
- uninstall_app_with_calabash
8
+ shutdown_test_kraken_server
10
9
  end
@@ -1 +1 @@
1
- require 'kraken-mobile/runners/calabash/android/cucumber'
1
+ require 'kraken-mobile/utils/mobile_cucumber'
@@ -0,0 +1,3 @@
1
+ if ENV["ADB_DEVICE_ARG"].nil?
2
+ require 'kraken-mobile/steps/web/kraken_steps'
3
+ end
@@ -0,0 +1,15 @@
1
+ if ENV["ADB_DEVICE_ARG"].nil?
2
+ require 'kraken-mobile/hooks/web_operations'
3
+
4
+ Before do |scenario|
5
+ start_test_kraken_server_in_background(
6
+ scenario: scenario
7
+ )
8
+ end
9
+
10
+ After do |scenario|
11
+ shutdown_test_kraken_server(
12
+ scenario: scenario
13
+ )
14
+ end
15
+ end
@@ -0,0 +1,94 @@
1
+ # Abstract class
2
+ class DeviceProcess
3
+ attr_accessor :id
4
+ attr_accessor :device
5
+ attr_accessor :test_scenario
6
+
7
+ #-------------------------------
8
+ # Constructors
9
+ #-------------------------------
10
+ def initialize(id:, device:, test_scenario:)
11
+ @id = id
12
+ @device = device
13
+ @test_scenario = test_scenario
14
+ end
15
+
16
+ #-------------------------------
17
+ # Required methods
18
+ #-------------------------------
19
+ def before_execute
20
+ raise 'ERROR: before_execute not implemented.'
21
+ end
22
+
23
+ def execute
24
+ raise 'ERROR: execute not implemented.'
25
+ end
26
+
27
+ def after_execute
28
+ raise 'ERROR: after_execute not implemented.'
29
+ end
30
+
31
+ def run
32
+ before_execute
33
+ execute
34
+ after_execute
35
+ end
36
+
37
+ #-------------------------------
38
+ # Methods
39
+ #-------------------------------
40
+ def register_process_to_directory
41
+ File.open(K::DIRECTORY_PATH, 'a') do |file|
42
+ file.puts("#{id}#{K::SEPARATOR}#{device}")
43
+ end
44
+ end
45
+
46
+ def notify_ready_to_start
47
+ File.open(K::DIRECTORY_PATH, 'a') do |file|
48
+ file.puts("#{id}#{K::SEPARATOR}#{device}")
49
+ end
50
+ end
51
+
52
+ def self.directory
53
+ return [] unless File.exist?(K::DIRECTORY_PATH)
54
+
55
+ directory = nil
56
+ File.open(K::DIRECTORY_PATH, 'r') do |file|
57
+ directory = file.each_line.map(&:to_s).map(&:strip)
58
+ end
59
+
60
+ directory || []
61
+ end
62
+
63
+ def self.registered_process_ids
64
+ directory = DeviceProcess.directory
65
+ directory.map do |entry|
66
+ info = entry.strip.split(K::SEPARATOR)
67
+ info[0]
68
+ end.compact.uniq
69
+ end
70
+
71
+ def self.notify_process_state(process_id:, state:)
72
+ raise 'ERROR: Process id can\'t be nil.' if process_id.nil?
73
+
74
+ file_path = K::PROCESS_STATE_FILE_PATH[state]
75
+ raise 'ERROR: State does not exist.' if file_path.nil?
76
+
77
+ File.open(file_path, 'a') do |file|
78
+ file.puts(process_id)
79
+ end
80
+ end
81
+
82
+ def self.processes_in_state(state)
83
+ file_path = K::PROCESS_STATE_FILE_PATH[state]
84
+ return [] if file_path.nil?
85
+ return [] unless File.exist?(file_path)
86
+
87
+ devices_ready = nil
88
+ File.open(file_path, 'r') do |file|
89
+ devices_ready = file.each_line.map(&:to_s).map(&:strip)
90
+ end
91
+
92
+ devices_ready || []
93
+ end
94
+ end
@@ -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,107 @@
1
+ require 'faker'
2
+ require 'kraken-mobile/utils/k'
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
+ JSON.parse(content)
60
+ end
61
+
62
+ def create_dictionary_json_file
63
+ absolute_dictionary_path = File.expand_path(K::DICTIONARY_PATH)
64
+ File.open(absolute_dictionary_path, 'w') do |f|
65
+ f.puts({}.to_json)
66
+ end
67
+ end
68
+
69
+ def dictionary_json_file_exists?
70
+ absolute_dictionary_path = File.expand_path(K::DICTIONARY_PATH)
71
+ File.file?(absolute_dictionary_path)
72
+ end
73
+
74
+ def save_key_value_in_dictionary(key:, value:)
75
+ current_json = dictionary_json
76
+ current_json[process_id.to_s] = {} if current_json[process_id.to_s].nil?
77
+ current_json[process_id.to_s][key.to_s] = value
78
+
79
+ absolute_dictionary_path = File.expand_path(K::DICTIONARY_PATH)
80
+ open(absolute_dictionary_path, 'w') do |f|
81
+ f.puts(current_json.to_json)
82
+ end
83
+ end
84
+
85
+ #-------------------------------
86
+ # Generators
87
+ #-------------------------------
88
+ def generate_name
89
+ Faker::Name.first_name
90
+ end
91
+
92
+ def generate_number
93
+ Faker::Number.number(digits: rand(10))
94
+ end
95
+
96
+ def generate_email
97
+ Faker::Internet.email
98
+ end
99
+
100
+ def generate_string
101
+ Faker::String.random(length: rand(100))
102
+ end
103
+
104
+ def generate_date
105
+ Faker::Date.in_date_period.to_s
106
+ end
107
+ end