friendly-cukes 0.0.1

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 (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