friendly-cukes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/DETAILED_DESCRIPTION.md +235 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +108 -0
  7. data/Rakefile +2 -0
  8. data/bin/build-extractor +69 -0
  9. data/bin/friendly-cukes +48 -0
  10. data/friendly-cukes.gemspec +41 -0
  11. data/lib/friendly/build_extractor.rb +647 -0
  12. data/lib/friendly/cukes.rb +29 -0
  13. data/lib/friendly/cukes/framework/Gemfile +16 -0
  14. data/lib/friendly/cukes/framework/Gemfile.lock +113 -0
  15. data/lib/friendly/cukes/framework/Rakefile.rb +19 -0
  16. data/lib/friendly/cukes/framework/config/config.yml +87 -0
  17. data/lib/friendly/cukes/framework/config/cucumber.yml +49 -0
  18. data/lib/friendly/cukes/framework/coverage/.last_run.json +5 -0
  19. data/lib/friendly/cukes/framework/coverage/.resultset.json +3519 -0
  20. data/lib/friendly/cukes/framework/coverage/.resultset.json.lock +0 -0
  21. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/jquery-1.3.2.min.js +19 -0
  22. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/jquery.tablesorter.min.js +15 -0
  23. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/print.css +12 -0
  24. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/rcov.js +42 -0
  25. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/screen.css +270 -0
  26. data/lib/friendly/cukes/framework/coverage/rcov/index.html +392 -0
  27. data/lib/friendly/cukes/framework/coverage/rcov/library-app_init-app_driver_rb.html +98 -0
  28. data/lib/friendly/cukes/framework/coverage/rcov/library-app_utils-data_file_names_rb.html +65 -0
  29. data/lib/friendly/cukes/framework/coverage/rcov/library-app_utils-page_utils_rb.html +533 -0
  30. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-create_log_rb.html +521 -0
  31. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-custom_html_report_rb.html +2522 -0
  32. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-datetime_library_rb.html +296 -0
  33. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-file_library_rb.html +995 -0
  34. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-performance_report_rb.html +1613 -0
  35. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-read_from_yml_rb.html +944 -0
  36. data/lib/friendly/cukes/framework/coverage/rcov/object_repository-desktop-gem_search_rb.html +773 -0
  37. data/lib/friendly/cukes/framework/coverage/rcov/object_repository-desktop-google_search_rb.html +230 -0
  38. data/lib/friendly/cukes/framework/coverage/rcov/object_repository-mobile-mobile_google_search_rb.html +230 -0
  39. data/lib/friendly/cukes/framework/coverage/rcov/step_definitions-desktop-gem_search_rb.html +188 -0
  40. data/lib/friendly/cukes/framework/coverage/rcov/step_definitions-desktop-google_search_steps_rb.html +167 -0
  41. data/lib/friendly/cukes/framework/coverage/rcov/step_definitions-mobile-mobile_google_search_steps_rb.html +167 -0
  42. data/lib/friendly/cukes/framework/coverage/rcov/support-browser_settings_rb.html +851 -0
  43. data/lib/friendly/cukes/framework/coverage/rcov/support-env_rb.html +242 -0
  44. data/lib/friendly/cukes/framework/coverage/rcov/support-hooks_rb.html +878 -0
  45. data/lib/friendly/cukes/framework/coverage/rcov/support-html_formatter_rb.html +230 -0
  46. data/lib/friendly/cukes/framework/features/desktop/google_search/google_search.feature +19 -0
  47. data/lib/friendly/cukes/framework/features/desktop/rubygems_search/gem_name_tc_04.yml +2 -0
  48. data/lib/friendly/cukes/framework/features/desktop/rubygems_search/gem_search.feature +37 -0
  49. data/lib/friendly/cukes/framework/features/desktop/test_data/gem_name.yml +2 -0
  50. data/lib/friendly/cukes/framework/features/mobile/google_search/mobile_google_search.feature +19 -0
  51. data/lib/friendly/cukes/framework/library/app_init/app_init.rb +13 -0
  52. data/lib/friendly/cukes/framework/library/app_utils/data_file_names.rb +2 -0
  53. data/lib/friendly/cukes/framework/library/app_utils/page_utils.rb +157 -0
  54. data/lib/friendly/cukes/framework/library/generic/app_logo_1.png +0 -0
  55. data/lib/friendly/cukes/framework/library/generic/create_log.rb +154 -0
  56. data/lib/friendly/cukes/framework/library/generic/custom_html_report.rb +852 -0
  57. data/lib/friendly/cukes/framework/library/generic/datetime_library.rb +79 -0
  58. data/lib/friendly/cukes/framework/library/generic/file_library.rb +311 -0
  59. data/lib/friendly/cukes/framework/library/generic/performance_report.rb +518 -0
  60. data/lib/friendly/cukes/framework/library/generic/read_from_yml.rb +294 -0
  61. data/lib/friendly/cukes/framework/object_repository/desktop/desktop_web_object_repo.rb +50 -0
  62. data/lib/friendly/cukes/framework/object_repository/mobile/mobile_web_object_repo.rb +22 -0
  63. data/lib/friendly/cukes/framework/page_objects/desktop/gem_search.rb +213 -0
  64. data/lib/friendly/cukes/framework/page_objects/desktop/google_search.rb +53 -0
  65. data/lib/friendly/cukes/framework/page_objects/mobile/mobile_google_search.rb +53 -0
  66. data/lib/friendly/cukes/framework/step_definitions/desktop/gem_search.rb +43 -0
  67. data/lib/friendly/cukes/framework/step_definitions/desktop/google_search_steps.rb +36 -0
  68. data/lib/friendly/cukes/framework/step_definitions/mobile/mobile_google_search_steps.rb +36 -0
  69. data/lib/friendly/cukes/framework/support/browser_settings.rb +264 -0
  70. data/lib/friendly/cukes/framework/support/env.rb +65 -0
  71. data/lib/friendly/cukes/framework/support/hooks.rb +274 -0
  72. data/lib/friendly/cukes/framework/support/html_formatter.rb +57 -0
  73. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/app_env.log +15 -0
  74. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/detailed_report/app_logo_1.png +0 -0
  75. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/detailed_report/desktop_gem_search.html +647 -0
  76. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/detailed_report/desktop_google_search.html +590 -0
  77. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/report_home.html +593 -0
  78. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/desktop_rubygems_search.log +84 -0
  79. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/report_21_05_2015-11_04_54.html +472 -0
  80. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/report_21_05_2015-11_04_54.json +299 -0
  81. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/app_env.log +15 -0
  82. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/desktop_google_search.log +22 -0
  83. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/report_21_05_2015-11_03_49.html +472 -0
  84. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/report_21_05_2015-11_03_49.json +155 -0
  85. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/app_env.log +15 -0
  86. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/mobile_google_search.log +22 -0
  87. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/report_21_05_2015-17_29_26.html +472 -0
  88. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/report_21_05_2015-17_29_26.json +143 -0
  89. data/lib/friendly/cukes/version.rb +61 -0
  90. metadata +309 -0
@@ -0,0 +1,154 @@
1
+ =begin
2
+ *Name : CreateLog
3
+ *Description : class that defines custom logger methods
4
+ *Author : Chandra sekaran
5
+ *Creation Date : 23/08/2014
6
+ *Updation Date :
7
+ =end
8
+
9
+ module CUKES
10
+ class CreateLog
11
+ include FileLibrary # module that define methods all file related manipulations
12
+ include DateTimeLibrary # module that define methods for all datetime related manipulations
13
+
14
+ # Description : initializes the Logger class and creates a new log file
15
+ # Author : Chandra sekaran
16
+ # Arguments :
17
+ # str_logfile_name: name of the log file to be created
18
+ #
19
+ def initialize(str_logfile_name = "log_")
20
+ begin
21
+ date_time_format = DATETIME_FORMAT || "%d_%m_%Y-%H_%M_%S"
22
+ rescue Exception => ex
23
+ date_time_format = "%d_%m_%Y-%H_%M_%S" # when DATETIME_FORMAT is not defined
24
+ end
25
+
26
+ begin
27
+ level = LOGGER_LEVEL || "DEBUG"
28
+ rescue Exception => ex
29
+ level = "DEBUG" # when LOGGER_LEVEL is not defined
30
+ end
31
+
32
+ begin
33
+ @str_logdir_name = $current_log_dir || "./test_result/test_report_#{Time.now.strftime(date_time_format)}" # this line is enough, ex handlng not need
34
+ rescue Exception => ex
35
+ @str_logdir_name = "./test_result/test_report_#{Time.now.strftime(date_time_format)}"
36
+ end
37
+
38
+ create_directory(@str_logdir_name) # creates a new directory
39
+ @log_file = "#{@str_logdir_name}/#{str_logfile_name}.log"
40
+ @log = Logger.new(@log_file) # creates a new log file
41
+ set_level(level) # sets the Logger::Level
42
+ @log.datetime_format = date_time_format # sets the datetime format
43
+ @log.formatter = lambda do |severity, datetime, progname, message|
44
+ "[#{Time.now.strftime(date_time_format)}] #{severity}: #{message}\n" # customize the log content
45
+ end
46
+ end
47
+
48
+ # Description : logs a DEBUG message
49
+ # Author : Chandra sekaran
50
+ # Arguments :
51
+ # message : string message to be logged
52
+ #
53
+ def debug(message)
54
+ @log.debug(message)
55
+ end
56
+
57
+ # Description : logs an INFO message
58
+ # Author : Chandra sekaran
59
+ # Arguments :
60
+ # message : string message to be logged
61
+ #
62
+ def info(message)
63
+ @log.info(message)
64
+ end
65
+
66
+ # Description : logs a WARN message
67
+ # Author : Chandra sekaran
68
+ # Arguments :
69
+ # message : string message to be logged
70
+ #
71
+ def warn(message)
72
+ @log.warn(message)
73
+ end
74
+
75
+ # Description : logs an ERROR message
76
+ # Author : Chandra sekaran
77
+ # Arguments :
78
+ # message : string message to be logged
79
+ #
80
+ def error(message)
81
+ @log.error(message)
82
+ #$world.puts(message) if !$world.nil?
83
+ #exit #raise #"EXCEPTION RAISED"#Cucumber.wants_to_quit = true # exit(1)
84
+ end
85
+
86
+ # Description : logs a success message
87
+ # Author : Chandra sekaran
88
+ # Arguments :
89
+ # message : string message to be logged
90
+ #
91
+ def success(message)
92
+ info(message)
93
+ $world.puts(message) if !$world.nil?
94
+ end
95
+
96
+ # Description : logs a FATAL message
97
+ # Author : Chandra sekaran
98
+ # Arguments :
99
+ # message : string message to be logged
100
+ #
101
+ def fatal(message)
102
+ @log.fatal(message)
103
+ end
104
+
105
+ # Description : sets the logger level
106
+ # Author : Chandra sekaran
107
+ # Arguments :
108
+ # level : logger level string
109
+ #
110
+ def set_level(level)
111
+ case level.upcase
112
+ when "DEBUG"
113
+ @log.level = Logger::DEBUG
114
+ when "INFO"
115
+ @log.level = Logger::INFO
116
+ when "WARN"
117
+ @log.level = Logger::WARN
118
+ when "ERROR"
119
+ @log.level = Logger::ERROR
120
+ when "FATAL"
121
+ @log.level = Logger::FATAL
122
+ end
123
+ end
124
+
125
+ # Description : creates a new directory under the given path (newly added to override the method in file_library.rb)
126
+ # Author : Chandra sekaran
127
+ # Arguments :
128
+ # str_directory_path : relative path of the directory to be created
129
+ #
130
+ def create_directory(str_directory_path)
131
+ unless File.directory?(str_directory_path)
132
+ FileUtils.mkdir_p(str_directory_path)
133
+ puts "New directory created under : #{str_directory_path}"
134
+ end
135
+ end
136
+
137
+ # Description : returns the relative path of currently created directory
138
+ # Author : Chandra sekaran
139
+ #
140
+ def get_current_log_dir
141
+ @str_logdir_name
142
+ end
143
+
144
+ # Description : returns the relative path of currently created file (logfile)
145
+ # Author : Chandra sekaran
146
+ #
147
+ def get_current_log_file
148
+ @log_file
149
+ end
150
+
151
+ private
152
+ attr_reader :log
153
+ end
154
+ end
@@ -0,0 +1,852 @@
1
+ =begin
2
+ *Name : CustomHtmlReport
3
+ *Description : class that holds custom report file generator methods
4
+ *Author : Chandra sekaran
5
+ *Creation Date : 11/11/2014
6
+ *Updation Date : 19/02/2015
7
+ =end
8
+
9
+ module CUKES
10
+ class CustomHtmlReport
11
+ include FileLibrary
12
+ include DateTimeLibrary
13
+
14
+ # Description : invoked automatically when an object of the class type is created
15
+ # Author : Chandra sekaran
16
+ # Arguments :
17
+ # arr_file_paths : array of html report file paths
18
+ #
19
+ def initialize(arr_file_paths)
20
+ @arr_file_name = arr_file_paths
21
+ @template_file_name = arr_file_paths.first # take the html template from first html file
22
+
23
+ @scenario=[]
24
+ @scenario_pass=[]
25
+ @scenario_fail=[]
26
+ @scenario_skip=[]
27
+ @scenario_pending=[]
28
+ @scenario_undefined=[]
29
+ @step=[]
30
+ @step_pass=[]
31
+ @step_fail=[]
32
+ @step_skip=[]
33
+ @step_pending=[]
34
+ @step_undefined=[]
35
+
36
+ @feature=[]
37
+ @arr_html_file_name = []
38
+ @arr_testcase_id = []
39
+ @arr_feature_id = []
40
+ end
41
+
42
+ # Description : creates new directory for custom report files and copies other dependents
43
+ # Author : Chandra sekaran
44
+ #
45
+ def create_report_directory
46
+ create_directory("#{$current_log_dir}/custom_report")
47
+ create_directory("#{$current_log_dir}/custom_report/detailed_report")
48
+ FileUtils.cp("library/generic/app_logo_1.png", "#{$current_log_dir}/custom_report/detailed_report")
49
+ # copy screenshot directory to custom_report directory for image attachment of custom report html files
50
+ FileUtils.cp_r("#{$current_log_dir}/screenshot", "#{$current_log_dir}/custom_report/detailed_report") rescue Exception
51
+ rescue Exception => ex
52
+ $log.error("Error in creating custom report directory : #{ex}")
53
+ exit
54
+ end
55
+
56
+ # Description : creates new html template object based cucumber report file generated
57
+ # Author : Chandra sekaran
58
+ # Arguments :
59
+ # str_file_path : file path of html file
60
+ # Return arguments :
61
+ # html_template : html object
62
+ #
63
+ def create_html_template(str_file_path)
64
+ html_template = Nokogiri::HTML(File.read(str_file_path))
65
+ html_template.xpath("//div[@id='label']/h1").each do |t|
66
+ t.replace("<br><div class='centr'>CUKES - TEST REPORT SUMMARY</div>")
67
+ end
68
+
69
+ bottom = Nokogiri::XML::Node.new("footer", html_template)
70
+ div = html_template.at_css("div.feature")
71
+ div.add_next_sibling(bottom)
72
+
73
+ html_template.at('footer')["id"] = "footer"
74
+
75
+ html_template.xpath("//div[@class='feature']").each do |n|
76
+ n.replace(Nokogiri::XML::Node.new("p", html_template))
77
+ end
78
+
79
+ footer = Nokogiri::XML::Node.new("div", html_template)
80
+ timestamp = Nokogiri::XML::Node.new("div", html_template)
81
+ timestamp.inner_html = "<font color='white' size='2'>Executed on #{Time.now.strftime('%m-%d-%Y %I:%M:%S')} <br> Executed in #{ENV['COMPUTERNAME']} (#{ENV['OS']}) / #{BROWSER.capitalize} (#{$browser_version})</font>"
82
+ logo = Nokogiri::XML::Node.new("img", html_template)
83
+
84
+ footer.add_child(logo)
85
+ footer.add_child(timestamp)
86
+
87
+ footer['style'] = "background-color: #363636;" # black color
88
+
89
+ footer.add_child("<style type='text/css'>#footer {position : fixed;margin-top : 35px;text-align:center;width: 100%;height: 63px;bottom: 0px; left: 0px;}</style>")
90
+ bottom.add_child(footer)
91
+ html_template.at('img')["src"] = "data:image/png;base64," + Base64.strict_encode64(File.open(File.absolute_path("library/generic/app_logo_1.png"), "rb").read)
92
+ html_template.at('img')["height"] = "30px"
93
+
94
+ html_template.xpath("//div[@id='summary']/p[1]").each do |t|
95
+ t.replace(Nokogiri::XML::Node.new("p", html_template)) # remove pass/fail count in the report header
96
+ end
97
+ html_template.xpath("//div[@id='summary']/p[2]").each do |t|
98
+ t.replace(Nokogiri::XML::Node.new("p", html_template)) # remove execution duration in the report header
99
+ end
100
+ return html_template
101
+ rescue Exception => ex
102
+ $log.error("Error in creating report html template : #{ex}")
103
+ exit
104
+ end
105
+
106
+ # Description : creates new html file holding complete execution summary
107
+ # Author : Chandra sekaran
108
+ #
109
+ def create_main_report
110
+ @html_template = create_html_template(@template_file_name)
111
+ template_header = @html_template.at_css "div#cucumber-header"
112
+ timestamp = Nokogiri::XML::Node.new("h4", @html_template)
113
+ timestamp.inner_html = "Executed on #{$log_env.get_formatted_datetime($start_time)}"
114
+ logo = Nokogiri::XML::Node.new("img", @html_template)
115
+ h1 = @html_template.at_css "h1"
116
+
117
+ br = Nokogiri::XML::Node.new("div", @html_template)
118
+ br.inner_html="<br><br><br>"
119
+
120
+ @table = Nokogiri::XML::Node.new("table", @html_template)
121
+
122
+ row_size = @feature.size
123
+
124
+ create_report_table_header
125
+
126
+ @tot_feature = 0
127
+ @tot_scenario = 0
128
+ @tot_scenario_pass = 0
129
+ @tot_scenario_fail = 0
130
+ @tot_scenario_skip = 0
131
+ @tot_scenario_pending = 0
132
+ @tot_scenario_undefined = 0
133
+ @tot_step = 0
134
+ @tot_step_pass = 0
135
+ @tot_step_fail = 0
136
+ @tot_step_skip = 0
137
+ @tot_step_pending = 0
138
+ @tot_step_undefined = 0
139
+
140
+ for i in 1..row_size
141
+ tr = Nokogiri::XML::Node.new("tr", @html_template)
142
+
143
+ td = Nokogiri::XML::Node.new("td", @html_template)
144
+ td.inner_html = "#{i}"
145
+ tr.add_child(td)
146
+ @tot_feature = i
147
+
148
+ if ["yes", "true"].include? INCLUDE_FEATUREID_IN_REPORT.downcase
149
+ td = Nokogiri::XML::Node.new("td", @html_template) # for Feature ID
150
+ td.inner_html = @arr_feature_id[i-1].nil? ? " " : @arr_feature_id[i-1].gsub("@", "").to_s
151
+ tr.add_child(td)
152
+ end
153
+
154
+ if ["yes", "true"].include? INCLUDE_SCENARIOID_IN_REPORT.downcase
155
+ td = Nokogiri::XML::Node.new("td", @html_template) # for Scenario ID
156
+ td.inner_html = @arr_testcase_id[i-1].nil? ? " " : @arr_testcase_id[i-1].join(", ").to_s
157
+ tr.add_child(td)
158
+ end
159
+
160
+ td = Nokogiri::XML::Node.new("td", @html_template)
161
+ td.inner_html = "<a href='detailed_report/#{@arr_html_file_name[i-1]}.html' target='_blank'>#{@feature[i-1]}</a>"
162
+ tr.add_child(td)
163
+ td['width'] = "40%"
164
+
165
+ td = Nokogiri::XML::Node.new("td", @html_template)
166
+ td.inner_html = "#{@scenario[i-1]}"
167
+ tr.add_child(td)
168
+ @tot_scenario += @scenario[i-1]
169
+
170
+ td = Nokogiri::XML::Node.new("td", @html_template)
171
+ num_pass_count = @scenario_pass[i-1]
172
+ td.inner_html = "#{num_pass_count}"
173
+ td['style'] = "background-color: #b0f9c3;" if num_pass_count > 0 # green color
174
+ tr.add_child(td)
175
+ @tot_scenario_pass += num_pass_count
176
+
177
+ td = Nokogiri::XML::Node.new("td", @html_template)
178
+ td.inner_html = "#{@scenario_fail[i-1]}"
179
+ td['style'] = "background-color: #fbc8d5;" if @scenario_fail[i-1] > 0 # red color
180
+ tr.add_child(td)
181
+ @tot_scenario_fail += @scenario_fail[i-1]
182
+
183
+ td = Nokogiri::XML::Node.new("td", @html_template)
184
+ td.inner_html = "#{@scenario_skip[i-1]}"
185
+ td['style'] = "background-color: #f2f9b0;" if @scenario_skip[i-1] > 0 # yellow color
186
+ tr.add_child(td)
187
+ @tot_scenario_skip += @scenario_skip[i-1]
188
+
189
+ td = Nokogiri::XML::Node.new("td", @html_template)
190
+ td.inner_html = "#{@scenario_pending[i-1]}"
191
+ td['style'] = "background-color: #f2f9b0;" if @scenario_pending[i-1] > 0 # yellow color
192
+ tr.add_child(td)
193
+ @tot_scenario_pending += @scenario_pending[i-1]
194
+
195
+ td = Nokogiri::XML::Node.new("td", @html_template)
196
+ td.inner_html = "#{@scenario_undefined[i-1]}"
197
+ td['style'] = "background-color: #f2f9b0;" if @scenario_undefined[i-1] > 0 # yellow color
198
+ tr.add_child(td)
199
+ @tot_scenario_undefined += @scenario_undefined[i-1]
200
+
201
+ td = Nokogiri::XML::Node.new("td", @html_template)
202
+ td.inner_html = "#{@step[i-1]}"
203
+ tr.add_child(td)
204
+ @tot_step += @step[i-1]
205
+
206
+ td = Nokogiri::XML::Node.new("td", @html_template)
207
+ td.inner_html = "#{@step_pass[i-1]}"
208
+ td['style'] = "background-color: #b0f9c3;" if @step_pass[i-1] > 0 # green color
209
+ tr.add_child(td)
210
+ @tot_step_pass += @step_pass[i-1]
211
+
212
+ td = Nokogiri::XML::Node.new("td", @html_template)
213
+ td.inner_html = "#{@step_fail[i-1]}"
214
+ td['style'] = "background-color: #fbc8d5;" if @step_fail[i-1] > 0 # red color
215
+ tr.add_child(td)
216
+ @tot_step_fail += @step_fail[i-1]
217
+
218
+ td = Nokogiri::XML::Node.new("td", @html_template)
219
+ td.inner_html = "#{@step_skip[i-1]}"
220
+ td['style'] = "background-color: #f2f9b0;" if @step_skip[i-1] > 0 # yellow color
221
+ tr.add_child(td)
222
+ @tot_step_skip += @step_skip[i-1]
223
+
224
+ td = Nokogiri::XML::Node.new("td", @html_template)
225
+ td.inner_html = "#{@step_pending[i-1]}"
226
+ td['style'] = "background-color: #f2f9b0;" if @step_pending[i-1] > 0 # yellow color
227
+ tr.add_child(td)
228
+ @tot_step_pending += @step_pending[i-1]
229
+
230
+ td = Nokogiri::XML::Node.new("td", @html_template)
231
+ td.inner_html = "#{@step_undefined[i-1]}"
232
+ td['style'] = "background-color: #f2f9b0;" if @step_undefined[i-1] > 0 # yellow color
233
+ tr.add_child(td)
234
+ @tot_step_undefined += @step_undefined[i-1]
235
+
236
+ td = Nokogiri::XML::Node.new("td", @html_template)
237
+ td.inner_html = @scenario_fail[i-1] > 0 ? "Failed" : "Passed"
238
+ td['style'] = @scenario_fail[i-1] > 0 ? "background-color: #fbc8d5;" : "background-color: #b0f9c3;"
239
+ tr.add_child(td)
240
+
241
+ @table.add_child(tr)
242
+ end
243
+
244
+ create_report_table_footer
245
+
246
+ @table['style'] = "width:90%; font:13px;"
247
+ 10.times { template_header.add_next_sibling("<br>") }
248
+ template_header.add_next_sibling(@table)
249
+ template_header.add_child("<style type='text/css'>td, th {color: black; font: normal 11.5px 'Lucida Grande', Helvetica, sans-serif;} .left{margin-left:50px;margin-top:20px;margin-bottom:20px;font:bold 12.5px 'Lucida Grande',Helvetica,sans-serif;} .centr{font-size:200%;font-weight:bold;text-align:center;}</script>")
250
+ @html_template.at('table')["border"] = 2
251
+ @html_template.at('table')["align"] = "center"
252
+
253
+ # set report header background color
254
+ if @tot_scenario_fail > 0 # for red color header
255
+ template_header.add_child("<script type='text/javascript'> $('#cucumber-header').css('background', '#c40d0d'); $('#cucumber-header').css('color', '#FFFFFF');</script>")
256
+ elsif @tot_scenario_pending > 0 # for yellow color header
257
+ template_header.add_child("<script type='text/javascript'> $('#cucumber-header').css('background', '#f2f9b0'); $('#cucumber-header').css('color', '#000000');</script>")
258
+ else # for green color header
259
+ template_header.add_child("<script type='text/javascript'> $('#cucumber-header').css('background', '#65c400'); $('#cucumber-header').css('color', '#FFFFFF');</script>")
260
+ end
261
+
262
+ @html_template.xpath("//div[@id='expand-collapse']").each do |t|
263
+ t.replace(Nokogiri::XML::Node.new("p", @html_template)) # removes Collapse All & Expand All links
264
+ end
265
+
266
+ # style : .left{margin-left:50px;margin-top:20px;margin-bottom:20px;font:bold 12.5px 'Lucida Grande',Helvetica,sans-serif;}
267
+ template_header.add_next_sibling("<div class='left' id='build_result'><b>Execution details : <b></div>")
268
+ build_res = @html_template.at_css "div#build_result"
269
+ arr_build_durations = get_execution_duration
270
+ # for getting individual build durations
271
+ #@arr_json_report_file.each_with_index do |file, indx|
272
+ # build_res.add_child("<div> Build - #{indx+1} duration : #{format_nonoseconds_to_time(arr_build_durations[indx])}</div>")
273
+ #end
274
+ build_res.add_child("<div> Total number of executions : #{@arr_json_report_file.size}</div>")
275
+ build_res.add_child("<div> Total duration (DD:HH:MM:SS) : #{format_nonoseconds_to_time(@num_build_duration)}</div>")
276
+ build_res.add_child("<div> Total build duration (DD:HH:MM:SS) : #{format_nonoseconds_to_time(arr_build_durations.max)}</div>")
277
+
278
+ File.open("#{$current_log_dir}/custom_report/report_home.html", "w") do |f|
279
+ f.write(@html_template)
280
+ end
281
+ rescue Exception => ex
282
+ $log.error("Error in creating main html report : #{ex}")
283
+ exit
284
+ end
285
+
286
+ # Description : creates new html files holding complete execution summary for each feature
287
+ # Author : Chandra sekaran
288
+ # Argument :
289
+ # str_file_path : file path of the report file
290
+ #
291
+ def create_sub_report(str_file_path)
292
+ @html_doc = Nokogiri::HTML(File.read(str_file_path))
293
+ br = Nokogiri::XML::Node.new("p", @html_doc)
294
+
295
+ @html_doc.xpath("//div[@class='feature']").each_with_index do |f, index|
296
+ @scenario_name = []
297
+ @num_step_count = []
298
+ @num_step_pass_count = []
299
+ @num_step_fail_count = []
300
+ @num_step_skip_count = []
301
+ @num_step_pending_count = []
302
+ @num_step_undefined_count = []
303
+
304
+ @html_template1 = create_html_template(@template_file_name)
305
+ # @html_template1.at('img')["src"] = "app_logo_1.png" # change the image file path for the sub-report files
306
+ @html_template1.at('img')["src"] = "data:image/png;base64," + Base64.strict_encode64(File.open(File.absolute_path("library/generic/app_logo_1.png"), "rb").read) # change the image file path for the sub-report files
307
+ template_header1 = @html_template1.at_css "div#cucumber-header"
308
+
309
+ @feature << f.xpath("./h2/span[@class='val']").text.gsub("Feature:", "")
310
+
311
+ begin # for feature documentation header content
312
+ pre_old = f.at_css "pre"
313
+ f.xpath("./pre").each do |t|
314
+ t.replace("<br><br><br><br><pre><font color='black'>")
315
+ end
316
+ font = f.at_css "font"
317
+ font.add_child(pre_old)
318
+ rescue Exception => ex
319
+ end
320
+
321
+ @scenario_skip_count = 0
322
+
323
+ cstep = 0
324
+ cstep_pass = 0
325
+ cstep_fail = 0
326
+ cstep_skip = 0
327
+ cstep_pending = 0
328
+ cstep_undefined = 0
329
+
330
+ bstep = 0
331
+ bstep_pass = 0
332
+ bstep_fail = 0
333
+ bstep_skip = 0
334
+ bstep_pending = 0
335
+
336
+ f.search("./div[@class='scenario']/h3").each do |s|
337
+ @scenario_name << s.inner_text.strip
338
+ end
339
+
340
+ f.search("./div[@class='background']").each do |s|
341
+ bstep = s.search(".//ol/li/div[@class='step_name']").size
342
+ bstep_pass = s.search(".//ol/li[@class='step passed']").size
343
+ bstep_fail = s.search(".//ol/li[@class='step failed']").size
344
+ bstep_skip = s.search(".//ol/li[@class='step skipped']").size
345
+ bstep_pending = s.search(".//ol/li[@class='step pending']").size
346
+ end
347
+
348
+ @scenario << f.search("./div[@class='scenario']").size
349
+ tmp = []
350
+ break_count = true # for getting scenario ID of scenario that has failed in Background itself
351
+ @pass_step_count = 0
352
+ @fail_step_count = 0
353
+ if bstep_fail > 0
354
+ f.search("./div[@class='scenario']").each_with_index do |s, indx|
355
+ cstep += bstep
356
+ cstep_fail = bstep_fail
357
+ cstep_skip += bstep_skip
358
+ cstep_pending += bstep_pending
359
+
360
+ cstep += s.search(".//ol/li/div[@class='step_name']").size
361
+ cstep_skip += s.search(".//ol/li[@class='step skipped']").size
362
+ cstep_pending += s.search(".//ol/li[@class='step pending']").size
363
+
364
+ @num_step_count << s.search(".//ol/li/div[@class='step_name']").size + bstep
365
+ @num_step_fail_count << bstep_fail
366
+ @num_step_skip_count << s.search(".//ol/li[@class='step skipped']").size
367
+ @num_step_pending_count << s.search(".//ol/li[@class='step pending']").size
368
+ @num_step_undefined_count << s.search(".//ol/li[@class='step undefined']").size
369
+
370
+ if s.search(".//ol/li/div[@class='step_name']").size == s.search(".//ol/li[@class='step skipped']").size
371
+ @scenario_skip_count += 1
372
+ elsif (s.search(".//ol/li/div[@class='step_name']").size - s.search(".//ol/li[@class='step skipped']").size) > 0
373
+ @scenario_skip_count += 1
374
+ end
375
+
376
+ # setting colors for the scenario IDs under the feature
377
+ s.search("./span[@class='tag'][1]").each do |tag|
378
+ if cstep_fail >= 1 && break_count
379
+ tmp << "<span style='color:red'>#{tag.inner_text.strip.gsub(SCENARIO_ID_PREFIX,"")}</span>"
380
+ break_count = false
381
+ @fail_step_count += 1
382
+ elsif s.search(".//ol/li[@class='step skipped']").size >= 1
383
+ tmp << "<span style='color:#B0A914'>#{tag.inner_text.strip.gsub(SCENARIO_ID_PREFIX,"")}</span>"
384
+ else
385
+ tmp << "<span style='color:green'>#{tag.inner_text.strip.gsub(SCENARIO_ID_PREFIX,"")}</span>"
386
+ end
387
+ end
388
+ end
389
+ scenario_undefined_count = 0
390
+ else
391
+ scenario_undefined_count = 0
392
+ f.search("./div[@class='scenario']").each_with_index do |s, indx|
393
+ cstep += bstep
394
+ cstep_pass += bstep_pass
395
+ cstep_fail += bstep_fail
396
+ cstep_skip += bstep_skip
397
+ cstep_pending += bstep_pending
398
+
399
+ cstep += s.search(".//ol/li/div[@class='step_name']").size
400
+ cstep_pass += s.search(".//ol/li[@class='step passed']").size
401
+ cstep_fail += s.search(".//ol/li[@class='step failed']").size
402
+ cstep_skip += s.search(".//ol/li[@class='step skipped']").size
403
+ cstep_pending += s.search(".//ol/li[@class='step pending']").size
404
+ cstep_undefined += s.search(".//ol/li[@class='step undefined']").size
405
+
406
+ @num_step_count << s.search(".//ol/li/div[@class='step_name']").size + bstep
407
+ @num_step_pass_count << s.search(".//ol/li[@class='step passed']").size + bstep_pass
408
+ @num_step_fail_count << s.search(".//ol/li[@class='step failed']").size
409
+ @num_step_skip_count << s.search(".//ol/li[@class='step skipped']").size
410
+ @num_step_pending_count << s.search(".//ol/li[@class='step pending']").size
411
+ @num_step_undefined_count << s.search(".//ol/li[@class='step undefined']").size
412
+
413
+ # setting colors for the scenario IDs under the feature
414
+ s.search("./span[@class='tag'][1]").each do |tag|
415
+ if s.search(".//ol/li[@class='step failed']").size >= 1
416
+ tmp << "<span style='color:red'>#{tag.inner_text.strip.gsub(SCENARIO_ID_PREFIX,"")}</span>"
417
+ @fail_step_count += 1
418
+ elsif s.search(".//ol/li[@class='step skipped']").size >= 1
419
+ tmp << "<span style='color:#B0A914'>#{tag.inner_text.strip.gsub(SCENARIO_ID_PREFIX,"")}</span>"
420
+ else
421
+ tmp << "<span style='color:green'>#{tag.inner_text.strip.gsub(SCENARIO_ID_PREFIX,"")}</span>"
422
+ end
423
+ end
424
+ if s.search(".//ol/li[@class='step undefined']").size > 0
425
+ scenario_undefined_count += 1 if s.search(".//ol/li[@class='step failed']").size == 0
426
+ end
427
+ if s.search(".//ol/li/div[@class='step_name']").size == s.search(".//ol/li[@class='step passed']").size
428
+ @pass_step_count += 1
429
+ end
430
+ end
431
+ end
432
+
433
+ # for getting the feature ID
434
+ f.search("./span[@class='tag']").each do |tag|
435
+ if tag.inner_text.include? FEATURE_ID_PREFIX
436
+ if cstep_fail >= 1
437
+ @arr_feature_id << "<span style='color:red'>#{tag.inner_text.gsub(FEATURE_ID_PREFIX, "")}</span>"
438
+ elsif cstep_pending >= 1
439
+ @arr_feature_id << "<span style='color:#B0A914'>#{tag.inner_text.gsub(FEATURE_ID_PREFIX, "")}</span>"
440
+ else
441
+ @arr_feature_id << "<span style='color:green'>#{tag.inner_text.gsub(FEATURE_ID_PREFIX, "")}</span>"
442
+ end
443
+ end
444
+ end
445
+
446
+ @scenario_pass << @pass_step_count
447
+ @scenario_fail << @fail_step_count
448
+
449
+ @step << cstep
450
+ @step_pass << cstep_pass
451
+ @step_fail << cstep_fail
452
+ @step_skip << cstep_skip
453
+ @step_pending << cstep_pending
454
+
455
+ if @scenario_skip_count - 1 < 0
456
+ @scenario_skip << 0
457
+ else
458
+ @scenario_skip << @scenario_skip_count - 1
459
+ end
460
+ @scenario_pending << cstep_pending
461
+ @step_undefined << cstep_undefined
462
+ @scenario_undefined << scenario_undefined_count
463
+
464
+ @arr_testcase_id << tmp
465
+
466
+ feature_name = f.xpath("./div[@class='scenario']/span[@class='scenario_file']").inner_text.strip
467
+ arr_feature_file_path = format_file_path(feature_name).split("/")
468
+ str_feature_name = arr_feature_file_path.pop.split(".").first
469
+ arr_feature_folder_name = arr_feature_file_path.pop(2)
470
+ html_file_name = "#{arr_feature_folder_name[0]}_#{str_feature_name}" # add stage name with fetaure file name
471
+ @arr_html_file_name << html_file_name
472
+
473
+ # table that summarises steps results for each scenario in the child html pages
474
+ @scenario_table = Nokogiri::XML::Node.new("table", @html_template1)
475
+ create_child_report_table_header
476
+
477
+ for i in 1..@scenario_name.size
478
+ tr = Nokogiri::XML::Node.new("tr", @html_template1)
479
+
480
+ td = Nokogiri::XML::Node.new("td", @html_template1)
481
+ td.inner_html = "#{i}"
482
+ tr.add_child(td)
483
+
484
+ td = Nokogiri::XML::Node.new("td", @html_template1) # for Scenario ID
485
+ td.inner_html = tmp[i-1].to_s
486
+ tr.add_child(td)
487
+
488
+ td = Nokogiri::XML::Node.new("td", @html_template1)
489
+ td.inner_html = @scenario_name[i-1].gsub("Scenario:", "").to_s
490
+ tr.add_child(td)
491
+ td["width"] = "40%"
492
+
493
+ td = Nokogiri::XML::Node.new("td", @html_template1)
494
+ td.inner_html = @num_step_count[i-1].to_s
495
+ tr.add_child(td)
496
+
497
+ td = Nokogiri::XML::Node.new("td", @html_template1)
498
+ td.inner_html = @num_step_pass_count[i-1].to_s
499
+ td['style'] = "background-color: #b0f9c3;" if @num_step_pass_count[i-1] > 0 # green color
500
+ tr.add_child(td)
501
+
502
+ td = Nokogiri::XML::Node.new("td", @html_template1)
503
+ td.inner_html = @num_step_fail_count[i-1].to_s
504
+ td['style'] = "background-color: #fbc8d5;" if @num_step_fail_count[i-1] > 0 # red color
505
+ tr.add_child(td)
506
+
507
+ td = Nokogiri::XML::Node.new("td", @html_template1)
508
+ td.inner_html = @num_step_skip_count[i-1].to_s
509
+ td['style'] = "background-color: #f2f9b0;" if @num_step_skip_count[i-1] > 0 # yellow color
510
+ tr.add_child(td)
511
+
512
+ td = Nokogiri::XML::Node.new("td", @html_template1)
513
+ td.inner_html = @num_step_pending_count[i-1].to_s
514
+ td['style'] = "background-color: #f2f9b0;" if @num_step_pending_count[i-1] > 0 # yellow color
515
+ tr.add_child(td)
516
+
517
+ td = Nokogiri::XML::Node.new("td", @html_template1)
518
+ td.inner_html = @num_step_undefined_count[i-1].to_s
519
+ td['style'] = "background-color: #f2f9b0;" if @num_step_undefined_count[i-1] > 0 # yellow color
520
+ tr.add_child(td)
521
+
522
+ td = Nokogiri::XML::Node.new("td", @html_template1)
523
+ td.inner_html = @num_step_fail_count[i-1] > 0 ? "Failed" : "Passed"
524
+ td['style'] = @num_step_fail_count[i-1] > 0 ? "background-color: #fbc8d5;" : "background-color: #b0f9c3;"
525
+ tr.add_child(td)
526
+
527
+ @scenario_table.add_child(tr)
528
+ end
529
+ create_child_report_table_footer
530
+ @scenario_table['style'] = "width:80%; font:13px;"
531
+ template_header1.add_next_sibling(@scenario_table)
532
+ template_header1.add_child("<style type='text/css'>td, th {color: black; font: normal 11.5px 'Lucida Grande', Helvetica, sans-serif;}</script>")
533
+ @html_template1.at('table')["border"] = 2
534
+ @html_template1.at('table')["align"] = "center"
535
+ font = f.at_css "font"
536
+ font.add_next_sibling(@scenario_table)
537
+
538
+ # try to add report table next to the feature title, but its not working
539
+ #feature_header = @html_template1.at_xpath("//div[@id='cucumber-header']/div[3]/div[1]")
540
+ ##feature_header.add_next_sibling(@scenario_table)
541
+ #@html_template1.xpath("//div[@id='cucumber-header']/div[3]/div[1]").each do |t|
542
+ # t.add_previous_sibling(@scenario_table)
543
+ #end
544
+ #@html_template1.at('table')["border"] = 2
545
+ #@html_template1.at('table')["align"] = "center"
546
+
547
+
548
+ template_header1.add_child(f) # add scenario with its steps as it is from cucumber report for this particular feature
549
+ 6.times { template_header1.add_child("<br>") }
550
+ h2 = @html_template1.at_css "h2"
551
+ h2["style"] = "color: black;"
552
+ failed_step = @html_template1.at_css("//li[@class='step failed']")
553
+ if !failed_step.nil?
554
+ template_header1.add_child("<script type='text/javascript'> $('#cucumber-header').css('background', '#C40D0D'); $('#cucumber-header').css('color', '#FFFFFF');</script>")
555
+ end
556
+ template_header1.xpath("//div[@id='label']/div").each do |t|
557
+ t.replace("<h1>#{html_file_name.gsub("_", " ").split.map(&:capitalize).join(' ')} - DETAILED REPORT</h1>")
558
+ end
559
+ template_header1.xpath("//div[@id='summary']/p[@id='duration']").each do |t|
560
+ t.replace("<p>") # remove duration fiels from cucumber report header
561
+ end
562
+
563
+ template_header1.add_child("<style type='text/css'>td, th {color: black; font: normal 11.5px 'Lucida Grande', Helvetica, sans-serif;}</script>")
564
+
565
+ File.open("#{$current_log_dir}/custom_report/detailed_report/#{html_file_name}.html", "w") do |file|
566
+ file.write(@html_template1)
567
+ end
568
+ end
569
+ @html_doc.xpath("//div[@class='feature']/div[@class='scenario']").each do |n|
570
+ n.replace(br)
571
+ end
572
+ rescue Exception => ex
573
+ $log.error("Error in creating sub report html : #{ex}")
574
+ exit
575
+ end
576
+
577
+ # Description : creates header for report table
578
+ # Author : Chandra sekaran
579
+ #
580
+ def create_report_table_header
581
+ arr_table_header = ["Sr No"]
582
+ arr_table_header << "Feature ID" if ["yes", "true"].include? INCLUDE_FEATUREID_IN_REPORT.downcase
583
+ arr_table_header << "Scenario ID" if ["yes", "true"].include? INCLUDE_SCENARIOID_IN_REPORT.downcase
584
+ arr_table_header += ["Feature","Total","Passed","Failed","Skipped","Pending","Undefined","Total","Passed","Failed","Skipped","Pending","Undefined","Result"]
585
+ tr = Nokogiri::XML::Node.new("tr", @html_template)
586
+ 5.times do |col|
587
+ td = Nokogiri::XML::Node.new("td", @html_template)
588
+ case col
589
+ when 1
590
+ td["colspan"] = "3"
591
+ td["colspan"] = (td["colspan"].to_i - 1).to_s if !(["yes", "true"].include?(INCLUDE_FEATUREID_IN_REPORT.downcase))
592
+ td["colspan"] = (td["colspan"].to_i - 1).to_s if !(["yes", "true"].include?(INCLUDE_SCENARIOID_IN_REPORT.downcase))
593
+ when 2
594
+ td["colspan"] = "6"
595
+ td.inner_html = "<b>Scenarios</b>"
596
+ td['align'] = "center"
597
+ when 3
598
+ td["colspan"] = "6"
599
+ td.inner_html = "<b>Steps</b>"
600
+ td['align'] = "center"
601
+ end
602
+ td['style'] = "background-color: #d3ecfc;"
603
+ tr.add_child(td)
604
+ end
605
+ @table.add_child(tr)
606
+
607
+ tr = Nokogiri::XML::Node.new("tr", @html_template)
608
+ arr_table_header.each do |str_header|
609
+ th = Nokogiri::XML::Node.new("th", @html_template)
610
+ th.inner_html = "<b>#{str_header}</b>"
611
+ th['style'] = "background-color: #d3ecfc;" # light blue color
612
+ th["font"] = "size: 15px;"
613
+ tr.add_child(th)
614
+ end
615
+ @table.add_child(tr)
616
+ rescue Exception => ex
617
+ $log.error("Error while creating report table header : #{ex}")
618
+ exit
619
+ end
620
+
621
+ # Description : creates footer for report table
622
+ # Author : Chandra sekaran
623
+ #
624
+ def create_report_table_footer
625
+ tr = Nokogiri::XML::Node.new("tr", @html_template)
626
+ num_col = 17
627
+ num_col -= 1 if !(["yes", "true"].include?(INCLUDE_FEATUREID_IN_REPORT.downcase))
628
+ num_col -= 1 if !(["yes", "true"].include?(INCLUDE_SCENARIOID_IN_REPORT.downcase))
629
+
630
+ bool_skip = false
631
+ num_col.times do |col|
632
+ td = Nokogiri::XML::Node.new("td", @html_template)
633
+ case col
634
+ when 1
635
+ if !(["yes", "true"].include?(INCLUDE_FEATUREID_IN_REPORT.downcase)) && !(["yes", "true"].include?(INCLUDE_SCENARIOID_IN_REPORT.downcase))
636
+ td.inner_html = "<b>Total<b>"
637
+ td["align"] = "right"
638
+ bool_skip = true
639
+ end
640
+ when 2
641
+ if (!(["yes", "true"].include?(INCLUDE_FEATUREID_IN_REPORT.downcase)) && (["yes", "true"].include?(INCLUDE_SCENARIOID_IN_REPORT.downcase))) || ((["yes", "true"].include?(INCLUDE_FEATUREID_IN_REPORT.downcase)) && !(["yes", "true"].include?(INCLUDE_SCENARIOID_IN_REPORT.downcase)))
642
+ td.inner_html = "<b>Total<b>"
643
+ td["align"] = "right"
644
+ bool_skip = true
645
+ end
646
+ when 3
647
+ if !bool_skip
648
+ td.inner_html = "<b>Total<b>"
649
+ td["align"] = "right"
650
+ end
651
+ when 4
652
+ td.inner_html = "<b>#{@tot_scenario.to_s}</b>"
653
+ when 5
654
+ td.inner_html = "<b>#{@tot_scenario_pass.to_s}</b>"
655
+ when 6
656
+ td.inner_html = "<b>#{@tot_scenario_fail.to_s}</b>"
657
+ when 7
658
+ td.inner_html = "<b>#{@tot_scenario_skip.to_s}</b>"
659
+ when 8
660
+ td.inner_html = "<b>#{@tot_scenario_pending.to_s}</b>"
661
+ when 9
662
+ td.inner_html = "<b>#{@tot_scenario_undefined.to_s}</b>"
663
+ when 10
664
+ td.inner_html = "<b>#{@tot_step.to_s}</b>"
665
+ when 11
666
+ td.inner_html = "<b>#{@tot_step_pass.to_s}<b>"
667
+ when 12
668
+ td.inner_html = "<b>#{@tot_step_fail.to_s}</b>"
669
+ when 13
670
+ td.inner_html = "<b>#{@tot_step_skip.to_s}</b>"
671
+ when 14
672
+ td.inner_html = "<b>#{@tot_step_pending.to_s}</b>"
673
+ when 15
674
+ td.inner_html = "<b>#{@tot_step_undefined.to_s}</b>"
675
+ end
676
+ td['style'] = "background-color: #d3ecfc;"
677
+ tr.add_child(td)
678
+ end
679
+ @table.add_child(tr)
680
+ rescue Exception => ex
681
+ $log.error("Error while creating report table footer : #{ex}")
682
+ exit
683
+ end
684
+
685
+ # Description : creates footer for report table for child pages
686
+ # Author : Chandra sekaran
687
+ #
688
+ def create_child_report_table_footer
689
+ begin
690
+ tr = Nokogiri::XML::Node.new("tr", @html_template1)
691
+ 10.times do |col|
692
+ td = Nokogiri::XML::Node.new("td", @html_template1)
693
+ case col
694
+ when 2
695
+ td.inner_html = "<b>Total<b>"
696
+ td["align"] = "right"
697
+ when 3
698
+ td.inner_html = "<b>#{@num_step_count.inject(:+).to_s}</b>"
699
+ when 4
700
+ td.inner_html = "<b>#{@num_step_pass_count.inject(:+).to_s}</b>"
701
+ when 5
702
+ td.inner_html = "<b>#{@num_step_fail_count.inject(:+).to_s}</b>"
703
+ when 6
704
+ td.inner_html = "<b>#{@num_step_skip_count.inject(:+).to_s}</b>"
705
+ when 7
706
+ td.inner_html = "<b>#{@num_step_pending_count.inject(:+).to_s}</b>"
707
+ when 8
708
+ td.inner_html = "<b>#{@num_step_undefined_count.inject(:+).to_s}</b>"
709
+ end
710
+ td['style'] = "background-color: #d3ecfc;"
711
+ tr.add_child(td)
712
+ end
713
+ @scenario_table.add_child(tr)
714
+ rescue Exception => ex
715
+ $log.error("Error while creating report table footer (for child pages): #{ex}")
716
+ exit
717
+ end
718
+ end
719
+
720
+ # Description : creates header for report table for child pages
721
+ # Author : Chandra sekaran
722
+ #
723
+ def create_child_report_table_header
724
+ begin
725
+ arr_table_header = ["Sr No","Scenario ID","Scenario Title","Total","Passed","Failed","Skipped","Pending","Undefined","Result"]
726
+ tr = Nokogiri::XML::Node.new("tr", @html_template1)
727
+ 4.times do |col|
728
+ td = Nokogiri::XML::Node.new("td", @html_template1)
729
+ case col
730
+ when 1
731
+ td["colspan"] = "2"
732
+ when 2
733
+ td["colspan"] = "6"
734
+ td.inner_html = "<b>Steps</b>"
735
+ td['align'] = "center"
736
+ end
737
+ td['style'] = "background-color: #d3ecfc;"
738
+ tr.add_child(td)
739
+ end
740
+ @scenario_table.add_child(tr)
741
+ tr = Nokogiri::XML::Node.new("tr", @html_template1)
742
+ arr_table_header.each do |str_header|
743
+ th = Nokogiri::XML::Node.new("th", @html_template1)
744
+ th.inner_html = "<b>#{str_header}</b>"
745
+ th['style'] = "background-color: #d3ecfc;" # light blue color
746
+ th["font"] = "size: 15px;"
747
+ tr.add_child(th)
748
+ end
749
+ @scenario_table.add_child(tr)
750
+ rescue Exception => ex
751
+ $log.error("Error while creating report table header for child pages : #{ex}")
752
+ exit
753
+ end
754
+ end
755
+
756
+ # Description : creates new custome html report files
757
+ # Author : Chandra sekaran
758
+ #
759
+ def create_custom_report
760
+ create_report_directory
761
+ @arr_file_name.each do |path| # move screenshot directory
762
+ path = format_file_path(path)
763
+ arr = path.split("/")
764
+ arr.pop # remove the html file name
765
+ path = arr.join("/")
766
+ Dir.glob(path).each do |file|
767
+ if File.directory?("#{file}/screenshot") # check if screenshot directory exists else create a new one and copy it to the recent log directory
768
+ create_directory("#{$current_log_dir}/custom_report/detailed_report/screenshot")
769
+ FileUtils.cp Dir["#{File.expand_path(file)}/screenshot/*.png"], "#{$current_log_dir}/custom_report/detailed_report/screenshot"
770
+ end
771
+ end
772
+ end
773
+ @arr_file_name.each do |path| # create sub report
774
+ create_sub_report(path)
775
+ end
776
+ create_main_report # create consolidated home report file
777
+ $log.success("Custom html report file has been generated successfully")
778
+ rescue Exception => ex
779
+ $log.error("Error in creating custom html report : #{ex}")
780
+ exit
781
+ end
782
+
783
+ # Description : gets the total execution duration with input data from json report file
784
+ # Author : Chandra sekaran
785
+ # Return argument :
786
+ # arr_build_durations : total execution time in nanoseconds
787
+ #
788
+ def get_execution_duration
789
+ @arr_json_report_file = get_files_absolute_path("test_result", "json", $start_time - $world.get_execution_delay_time.seconds)
790
+ $log.info("Report file names (json): #{@arr_json_report_file}")
791
+ @num_build_duration = 0
792
+
793
+ arr_build_durations = []
794
+
795
+ @arr_json_report_file.each do |path|
796
+ @arr_background_step_duration = []
797
+ file = File.read(path)
798
+ @json = JSON.parse(file)
799
+ arr_build_durations << parse_json # parse each json file and extract report data
800
+ end
801
+ arr_build_durations
802
+ end
803
+
804
+ # Description : parses the json file and calculates the total execution duration
805
+ # Author : Chandra sekaran
806
+ # Return argument :
807
+ # feature_duration : total execution time for each execution in nanoseconds
808
+ #
809
+ def parse_json
810
+ unit_build_duration = 0
811
+ feature_duration = 0
812
+ scenario_duration = 0
813
+ step_duration = 0
814
+ @json.each_with_index do |json, index| # iterate each feature
815
+ feature_duration = 0
816
+ json["elements"].each do |element|
817
+ # for including the first background steps duration to the first scenario background steps as Cucumber json
818
+ # report considers background for the first scenario and hence will have 0 duration for the background steps
819
+ # under first scenario and the actual duration for the background will be set for the subsequent scenarios
820
+ if index == 0
821
+ if element["keyword"] == "Background"
822
+ element["steps"].each do |step|
823
+ @arr_background_step_duration << step["result"]["duration"].to_i
824
+ @bool = true
825
+ end
826
+ end
827
+ end
828
+ if element["keyword"] == "Scenario" # take scenario for scenario level details
829
+ scenario_duration = 0
830
+ element["steps"].each_with_index do |step, indx| # iterate each steps of the current scenario
831
+ step_duration = 0
832
+ if (index == 0) && (indx < @arr_background_step_duration.size) && @bool
833
+ step_duration = @arr_background_step_duration[indx] # take duration from Background for the first scenario
834
+ else
835
+ step_duration = step["result"]["duration"].to_i # take usual duration
836
+ @bool = false
837
+ end
838
+ scenario_duration += step_duration
839
+ end
840
+ feature_duration += scenario_duration
841
+ end
842
+ end
843
+ @num_build_duration += feature_duration
844
+ unit_build_duration += feature_duration
845
+ end
846
+ unit_build_duration
847
+ rescue Exception => ex
848
+ $log.error("Error while parsing JSON : #{ex}")
849
+ exit
850
+ end
851
+ end
852
+ end