SurfCustomCalabash 0.2.0 → 1.0.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +68 -4
  4. data/SurfCustomCalabash.gemspec +3 -3
  5. data/bin/SurfCustomCalabash +54 -0
  6. data/bin/surf-calabash-console.rb +62 -0
  7. data/bin/surf-calabash-gen.rb +17 -0
  8. data/bin/surf-calabash-helpers.rb +34 -0
  9. data/lib/SurfCustomCalabash/CommonMethods.rb +3 -3
  10. data/lib/SurfCustomCalabash/DroidMethods.rb +2 -1
  11. data/lib/SurfCustomCalabash/IosMethods.rb +2 -2
  12. data/lib/SurfCustomCalabash/version.rb +1 -1
  13. data/sources/Backdoors list b/data/sources/Backdoors → list +0 -0
  14. data/sources/Gemfile +27 -0
  15. data/sources/Scripts/and.sh +5 -0
  16. data/sources/Scripts/ca.sh +5 -0
  17. data/sources/Scripts/ci.sh +5 -0
  18. data/sources/Scripts/data +7 -0
  19. data/sources/Scripts/fa.sh +6 -0
  20. data/sources/Scripts/fi.sh +5 -0
  21. data/sources/Scripts/get_apk.rb +68 -0
  22. data/sources/Scripts/get_scenarios.rb +193 -0
  23. data/sources/Scripts/import_scenarios.rb +172 -0
  24. data/sources/Scripts/ios.sh +5 -0
  25. data/sources/Scripts/parallel_android_smoke.sh +4 -0
  26. data/sources/Scripts/parallel_android_test.sh +4 -0
  27. data/sources/Scripts/ra.sh +12 -0
  28. data/sources/Scripts/ri.sh +9 -0
  29. data/sources/Scripts/smoke_and.sh +5 -0
  30. data/sources/Scripts/smoke_ios.sh +5 -0
  31. data/sources/Scripts/ta.sh +5 -0
  32. data/sources/Scripts/ti.sh +5 -0
  33. data/sources/Scripts/to_exec.sh +19 -0
  34. data/sources/Scripts/update.sh +24 -0
  35. data/sources/Scripts/update_exec.rb +96 -0
  36. data/sources/TestFolder/small.gif +0 -0
  37. data/sources/ci/JenkinsfileUiTestAndroid.groovy +22 -0
  38. data/sources/ci/JenkinsfileUiTestIos.groovy +23 -0
  39. data/sources/config/cucumber.yml +24 -0
  40. data/sources/features/android/pages/standard/DroidCommon.rb +33 -0
  41. data/sources/features/android/pages/standard/Init_android.rb +8 -0
  42. data/sources/features/android/pages/test.rb +43 -0
  43. data/sources/features/android/support/app_life_cycle_hooks.rb +147 -0
  44. data/sources/features/android/support/log_hooks_and.rb +40 -0
  45. data/sources/features/android/support/video_hooks_and.rb +110 -0
  46. data/sources/features/ios/pages/standard/Init_ios.rb +5 -0
  47. data/sources/features/ios/pages/standard/IosCommon.rb +30 -0
  48. data/sources/features/ios/pages/test.rb +37 -0
  49. data/sources/features/ios/support/01_launch.rb +194 -0
  50. data/sources/features/ios/support/log_hooks_ios.rb +40 -0
  51. data/sources/features/ios/support/video_hooks_ios.rb +58 -0
  52. data/sources/features/net/net.rb +28 -0
  53. data/sources/features/net/screentest_api.rb +186 -0
  54. data/sources/features/scenarios/eng.feature +8 -0
  55. data/sources/features/scenarios/rus.feature +8 -0
  56. data/sources/features/step_definitions/test.rb +43 -0
  57. data/sources/features/support/credentials.rb +11 -0
  58. data/sources/features/support/env.rb +8 -0
  59. data/sources/features/support/hooks.rb +21 -0
  60. data/sources/features/support/localization.rb +8 -0
  61. data/sources/find_id.rb +95 -0
  62. data/sources/group_steps.rb +39 -0
  63. data/sources/irbrcs/android/irbrc +105 -0
  64. data/sources/irbrcs/ios/irbrc +132 -0
  65. data/sources/start.sh +134 -0
  66. metadata +63 -6
  67. data/bin/console +0 -14
  68. data/bin/setup +0 -8
@@ -0,0 +1,110 @@
1
+ require 'open3'
2
+ require 'timeout'
3
+ require 'process'
4
+ require 'calabash-android/operations'
5
+ require 'calabash-android/env'
6
+ require 'streamio-ffmpeg'
7
+
8
+ def adb_command
9
+ "\"#{Calabash::Android::Dependencies.adb_path}\""
10
+ end
11
+
12
+ class ScreenRecord
13
+
14
+ # определяем поддерживает ли устройсвто запись через adb или scrcpy
15
+ def self.get_adb_or_scr
16
+ if Open3.capture2e("#{adb_command} shell screenrecord --help").first.include? "Options:"
17
+ return "adb"
18
+ elsif Open3.capture2e("scrcpy --help").first.include? "Options:"
19
+ return "scrcpy"
20
+ else
21
+ return "adb and scrcpy not install"
22
+ end
23
+ end
24
+ end
25
+
26
+ class AndroidVideoCapture
27
+
28
+ def initialize
29
+ @video_file = "video_#{Time.now.strftime('%d_%m-%H:%M:%S')}.mp4"
30
+
31
+ # определяем поддерживает ли устройсвто запись через adb или scrcpy
32
+ @command = ScreenRecord.get_adb_or_scr
33
+
34
+ # качество видео при конвертации
35
+ @quality = "low"
36
+ end
37
+
38
+ attr_accessor :video_file, :quality
39
+
40
+ # запускаем запись видео
41
+ def start_capture
42
+ if @command == "adb"
43
+ @screenrecord = Open3.popen2e("#{adb_command} shell")
44
+ # для улучшения качества видео, увеличить битрейт или убрать параметр совсем, по умолчанию пишется в хорошем качестве
45
+ @screenrecord[0] << "screenrecord --verbose --bit-rate 1000000 /sdcard/#{@video_file} &\n"
46
+ @screenrecord[0] << "CPID=$!\n"
47
+ elsif @command == "scrcpy"
48
+ @screenrecord = Open3.popen2e("scrcpy -m 1024 -b 2M --max-fps 10 -Nr #{@video_file}")
49
+ @pid = @screenrecord[2].pid
50
+ end
51
+ end
52
+
53
+ # останавливаем запись видео
54
+ def stop_capture
55
+
56
+ if @command == "adb"
57
+ @screenrecord[0] << "if ps | grep screenrecord | grep $CPID; then kill -2 $CPID ; fi\n"
58
+ elsif @command == "scrcpy"
59
+ %x{kill -SIGINT #{@pid}}
60
+ end
61
+
62
+ begin
63
+ Timeout.timeout(5) { @screenrecord[2].value }
64
+ rescue Timeout::Error
65
+ Process.detach(@screenrecord[2].pid)
66
+ end
67
+
68
+ @screenrecord[0].close
69
+ @screenrecord[1].close
70
+
71
+ end
72
+
73
+ # удаляем видео с устройства если была запись через adb
74
+ def dispose_capture
75
+ system "#{adb_command} shell rm -f /sdcard/#{@video_file}" if @command == "adb"
76
+ end
77
+
78
+ # сбрасываем видео с устройства в папку с тестами
79
+ def acquire_capture
80
+ if @command == "adb"
81
+ system "#{adb_command} pull /sdcard/#{@video_file} ."
82
+ dispose_capture
83
+ end
84
+ end
85
+
86
+ # конвертируем видео
87
+ def convert_video(path_to_input, path_to_output, quality = @quality)
88
+ movie = FFMPEG::Movie.new(path_to_input)
89
+
90
+ Kernel.puts "size #{movie.size}"
91
+
92
+ options = {video_codec: "h264", frame_rate: '10', resolution: "320x180"}
93
+ transcoder_options = {preserve_aspect_ratio: :width}
94
+
95
+ case quality.downcase
96
+ when "low"
97
+ options.merge!({video_bitrate: 100})
98
+ when "medium"
99
+ options.merge!({video_bitrate: 500})
100
+ when "high"
101
+ options.merge!({resolution: "720x480", video_bitrate: 1000})
102
+ else
103
+ return p "Please set video quality: high, medium or low"
104
+ end
105
+
106
+ Timeout.timeout(60) {
107
+ movie.transcode(path_to_output, options, transcoder_options)
108
+ }
109
+ end
110
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'IosCommon'
2
+ def init_ios
3
+ $main = Test.new(self)
4
+ # write here creating new class instances like example above this line
5
+ end
@@ -0,0 +1,30 @@
1
+ require 'calabash-cucumber/ibase'
2
+ require 'SurfCustomCalabash/IosMethods'
3
+
4
+
5
+ class IosCommon < Calabash::IBase
6
+
7
+ # system method
8
+ def initialize(driver)
9
+ @driver = driver
10
+ end
11
+
12
+ def method_missing (sym, *args, &block)
13
+ @driver.send sym, *args, &block
14
+ end
15
+
16
+ def self.element(name, &block)
17
+ define_method(name.to_s, &block)
18
+ end
19
+
20
+ class << self
21
+ alias :value :element
22
+ alias :action :element
23
+ alias :trait :element
24
+ end
25
+
26
+ # custom methods
27
+
28
+ end
29
+
30
+
@@ -0,0 +1,37 @@
1
+ require_relative 'standard/IosCommon'
2
+ # all screens your application screens should be like this. Inheritance from IosCommon is essential!
3
+
4
+ class Test < IosCommon
5
+
6
+ def initialize(driver)
7
+ @driver = driver
8
+
9
+
10
+ ##### elements on the screen #######
11
+ # locators and their x-platform nickname should be like that
12
+
13
+ @trait = "SegmentedPageControllerButton"
14
+
15
+ @auth_field = "* id:'auth_fld'"
16
+
17
+ @main_ok_button = "* id:'bigSpaceBackground'"
18
+
19
+ super(driver)
20
+ end
21
+
22
+ # all elements above should have getter for mention them from step definitions
23
+ attr_reader *Test.new(self).instance_variables.map {|s| s[1..-1]}
24
+
25
+ # another way to describe elements
26
+ def tape
27
+ "* id:'feed_rv'"
28
+ end
29
+
30
+
31
+ #### methods ####
32
+ def authorize(data)
33
+ tap_on(@auth_field)
34
+ wait_for_keyboard
35
+ enter_text(data)
36
+ end
37
+ end
@@ -0,0 +1,194 @@
1
+ require 'calabash-cucumber/launcher'
2
+ require 'calabash-cucumber/cucumber'
3
+ require_relative '../../support/env'
4
+ require_relative '../../../features/net/screentest_api'
5
+ require 'fileutils'
6
+
7
+
8
+ module Calabash::Launcher
9
+ @@launcher = nil
10
+
11
+ def self.launcher
12
+ @@launcher ||= Calabash::Cucumber::Launcher.new
13
+ end
14
+
15
+ def self.launcher=(launcher)
16
+ @@launcher = launcher
17
+ end
18
+ end
19
+
20
+
21
+ Before ('@reinstall') do
22
+ ENV['RESET_BETWEEN_SCENARIOS'] = '1'
23
+ end
24
+
25
+ Before('@screentest') do |scenario|
26
+
27
+ clear_file_with_stack_trace
28
+ @scenario_name = scenario.name
29
+ create_feature(@scenario_name)
30
+
31
+ end
32
+
33
+
34
+ Before do |scenario|
35
+
36
+ begin
37
+ calabash_exit
38
+ rescue HTTPClient::ReceiveTimeoutError => e
39
+ Kernel.puts(e)
40
+ end
41
+
42
+ ENV['SCREENSHOT_PATH'] = './reports/'
43
+
44
+ scenario_tags = scenario.source_tag_names
45
+
46
+ @start_record = true
47
+ @start_log = false
48
+
49
+ # Scenario name
50
+ @scenario_name = scenario.name
51
+
52
+ launcher = Calabash::Launcher.launcher
53
+ options = {
54
+ # Add launch options here.
55
+ }
56
+
57
+ launcher.relaunch(:timeout => 300)
58
+ ENV['RESET_BETWEEN_SCENARIOS'] = ''
59
+
60
+ if scenario_tags.include?('@record')
61
+ @start_record = true
62
+ end
63
+
64
+ @video_capture = nil
65
+
66
+ # start record video
67
+ if @start_record
68
+ @video_capture = IosCapture.new
69
+ @video_capture.start_capture
70
+ @need_convert = false
71
+ # set video quality: low, medium, high
72
+ @video_capture.quality = "low"
73
+ end
74
+
75
+ @write_log = nil
76
+
77
+ # start write logs
78
+ if @start_log
79
+ @write_log = IosLogs.new
80
+ @write_log.start_log
81
+ end
82
+ end
83
+
84
+ After do
85
+ # Calabash can shutdown the app cleanly by calling the app life cycle methods
86
+ # in the UIApplicationDelegate. This is really nice for CI environments, but
87
+ # not so good for local development.
88
+ #
89
+ # See the documentation for QUIT_APP_AFTER_SCENARIO for a nice debugging workflow
90
+ #
91
+ # http://calabashapi.xamarin.com/ios/file.ENVIRONMENT_VARIABLES.html#label-QUIT_APP_AFTER_SCENARIO
92
+ # http://calabashapi.xamarin.com/ios/Calabash/Cucumber/Core.html#console_attach-instance_method
93
+
94
+ begin
95
+ calabash_exit
96
+ rescue HTTPClient::ReceiveTimeoutError => e
97
+ Kernel.puts(e)
98
+ end
99
+
100
+ end
101
+
102
+ def file_name(ext)
103
+ "iOS_#{Time.now.strftime('%d_%m-%H:%M:%S')}.#{ext}"
104
+ end
105
+
106
+ def create_folder
107
+ @path = "#{ENV['SCREENSHOT_PATH']}#{@scenario_name}_#{Time.now.strftime('%d_%m-%H:%M:%S')}/"
108
+ # Dir.mkdir(@path) unless File.directory?(@path)
109
+ FileUtils.mkdir_p @path
110
+ end
111
+
112
+ def convert
113
+ convert_file = "video_#{file_name('mp4')}"
114
+ @video_capture.convert_video(@video_capture.video_file, convert_file)
115
+ delete_file(@video_capture.video_file)
116
+ @video_capture.video_file = convert_file
117
+ end
118
+
119
+ def embed_video
120
+ unless @video_capture.nil?
121
+ if File.exist?(@video_capture.video_file)
122
+ convert if @need_convert
123
+ sleep(2)
124
+ embed(@video_capture.video_file, 'video/mp4', "video #{@video_capture.video_file}")
125
+ FileUtils.mv(@video_capture.video_file, @path)
126
+ @video_capture.video_file = @path + @video_capture.video_file
127
+ end
128
+ end
129
+ end
130
+
131
+ def delete_file(file_name)
132
+ if File.exist?(file_name)
133
+ File.delete(file_name)
134
+ end
135
+ end
136
+
137
+ def embed_logs
138
+ unless @write_log.nil?
139
+ if File.exist?(@write_log.log_file)
140
+ embed(@write_log.log_file, 'log/txt', "log #{@write_log.log_file}")
141
+ FileUtils.mv(@write_log.log_file, @path)
142
+ end
143
+ end
144
+ end
145
+
146
+ After do |scenario|
147
+
148
+ @video_capture.stop_capture unless @video_capture.nil?
149
+
150
+ @write_log.stop_log unless @write_log.nil?
151
+
152
+ scenario_tags = scenario.source_tag_names
153
+
154
+ if scenario_tags.include?('@record') && scenario.passed?
155
+ create_folder
156
+ embed_video
157
+ # Kernel.puts("file name #{@video_capture.video_file}")
158
+ elsif scenario.passed?
159
+ delete_file(@write_log.log_file) unless @write_log.nil?
160
+ delete_file(@video_capture.video_file) unless @video_capture.nil?
161
+ end
162
+
163
+ if scenario.failed?
164
+
165
+ create_folder
166
+ mark_feature_as_not_finished if scenario_tags.include?('@screentest')
167
+
168
+ pretty = JSON.pretty_generate(query("*"))
169
+ parsed = JSON.parse(pretty)
170
+
171
+ for i in 0..query("*").count-1
172
+ id = parsed[i]['id'].to_s
173
+ text = parsed[i]['text'].to_s
174
+ label = parsed[i]['label'].to_s
175
+ if id != ''
176
+ File.open("#{@path}id_#{file_name('txt')}", 'a', crlf_newline: true) { |f| f.puts(id.encode(crlf_newline: true))}
177
+ end
178
+ if text != ''
179
+ File.open("#{@path}text_#{file_name('txt')}", 'a', crlf_newline: true) { |f| f.puts(text.encode(crlf_newline: true))}
180
+ end
181
+ if label != ''
182
+ File.open("#{@path}label_#{file_name('txt')}", 'a', crlf_newline: true) { |f| f.puts(label.encode(crlf_newline: true))}
183
+ end
184
+ end
185
+
186
+ screenshot(prefix: @path, name: "#{file_name('png')}")
187
+
188
+ embed_video
189
+ embed_logs
190
+ end
191
+
192
+ send_video(@video_capture.video_file) if scenario_tags.include?('@record')
193
+
194
+ end
@@ -0,0 +1,40 @@
1
+ require 'open3'
2
+ require 'timeout'
3
+ require 'process'
4
+
5
+ def adb_command
6
+ "\"#{Calabash::Android::Dependencies.adb_path}\""
7
+ end
8
+
9
+ class IosLogs
10
+
11
+ def initialize
12
+ @log_file = "#{ENV['SCREENSHOT_PATH']}log_#{Time.now.strftime('%d_%m-%H:%M:%S')}.txt"
13
+ end
14
+
15
+ attr_reader :log_file
16
+
17
+ def start_log
18
+ @logcat = Open3.popen2e("xcrun simctl spawn booted log stream")
19
+ @pid = @logcat[2].pid
20
+ end
21
+
22
+ def stop_log
23
+ @stoplog = Open3.popen2e("kill -SIGINT #{@pid}")
24
+
25
+ begin
26
+ Timeout.timeout(10) { File.open(@log_file, 'w') { |f| f << @logcat[1].readlines.join("\n") } }
27
+ rescue Timeout::Error
28
+ Kernel.puts("Error write log file")
29
+ @logcat[0].close
30
+ @logcat[1].close
31
+ end
32
+
33
+ @stoplog[0].close
34
+ @stoplog[1].close
35
+
36
+ @logcat[0].close
37
+ @logcat[1].close
38
+ end
39
+
40
+ end
@@ -0,0 +1,58 @@
1
+ require 'open3'
2
+ require 'timeout'
3
+ require 'streamio-ffmpeg'
4
+
5
+ class IosCapture
6
+
7
+ def initialize
8
+ @video_file = "video_#{Time.now.strftime('%d_%m-%H_%M_%S')}.mp4"
9
+
10
+ @quality = "low"
11
+
12
+ # h264 or hevc
13
+ @codec = "hevc"
14
+ end
15
+
16
+ attr_accessor :video_file, :quality
17
+
18
+ def start_capture(codec = @codec)
19
+ @screenrecord = Open3.popen2e("xcrun simctl io booted recordVideo --codec=#{codec} #{@video_file} \n")
20
+ # @screenrecord = Open3.popen2e("xcrun simctl io booted recordVideo #{@video_file} \n")
21
+ @pid = @screenrecord[2].pid
22
+ Kernel.puts("start record")
23
+ end
24
+
25
+ def stop_capture
26
+ @stoprecord = Open3.popen2e("kill -SIGINT #{@pid}")
27
+
28
+ @screenrecord[0].close
29
+ @screenrecord[1].close
30
+
31
+ @stoprecord[0].close
32
+ @stoprecord[1].close
33
+
34
+ Kernel.puts("video stopped")
35
+ end
36
+
37
+ def convert_video(path_to_input, path_to_output, quality = @quality)
38
+ movie = FFMPEG::Movie.new(path_to_input)
39
+
40
+ options = {video_codec: "h264", frame_rate: '10', resolution: "320x180"}
41
+ transcoder_options = {preserve_aspect_ratio: :width}
42
+
43
+ case quality.downcase
44
+ when "low"
45
+ options.merge!({video_bitrate: 100})
46
+ when "medium"
47
+ options.merge!({video_bitrate: 500})
48
+ when "high"
49
+ options.merge!({resolution: "720x480", video_bitrate: 1000})
50
+ else
51
+ return p "Please set video quality: high, medium or low"
52
+ end
53
+
54
+ Timeout.timeout(60) {
55
+ movie.transcode(path_to_output, options, transcoder_options)
56
+ }
57
+ end
58
+ end