kraken-mobile 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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