nxgreport 0.10.0 → 0.11.3
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.
- checksums.yaml +4 -4
- data/lib/nxgreport.rb +3 -3
- data/lib/nxgreport/nxgcore.rb +217 -0
- data/lib/{nxgcss.rb → nxgreport/nxgcss.rb} +62 -10
- data/lib/nxgreport/nxghtml.rb +196 -0
- data/lib/nxgreport/nxgjs.rb +233 -0
- data/lib/nxgreport/version.rb +3 -0
- metadata +43 -11
- data/lib/nxgcore.rb +0 -539
@@ -0,0 +1,233 @@
|
|
1
|
+
|
2
|
+
module NxgJavascript
|
3
|
+
|
4
|
+
def js_detect_system_dark_mode()
|
5
|
+
"if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
6
|
+
$(document.documentElement).attr(\"theme\", \"dark\");
|
7
|
+
}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def js(data_provider)
|
11
|
+
|
12
|
+
js_array = data_provider[:features].to_s.gsub("=>", ":")
|
13
|
+
|
14
|
+
return "<script>
|
15
|
+
const allFeatures = #{js_array};
|
16
|
+
const STATUS = { pass: \"check_circle\", fail: \"cancel\", };
|
17
|
+
var displayFailuresOnly = false;
|
18
|
+
var dataSource = [];
|
19
|
+
var catergories = [];
|
20
|
+
|
21
|
+
function onRefresh() {
|
22
|
+
dataSource = allFeatures;
|
23
|
+
setFilter();
|
24
|
+
currentTheme = $(document.documentElement).attr(\"theme\");
|
25
|
+
$(\"#theme-icon\").text(currentTheme === \"dark\" ? \"brightness_2\" : \"wb_sunny\");
|
26
|
+
}
|
27
|
+
|
28
|
+
function updateView() {
|
29
|
+
$(\".banner\").removeClass(\"banner\").addClass(\"features-grid\");
|
30
|
+
$(\".features-grid\").empty();
|
31
|
+
|
32
|
+
if (dataSource.length === 0) {
|
33
|
+
console.log(\"inside\");
|
34
|
+
$(\".features-grid\")
|
35
|
+
.removeClass(\"features-grid\")
|
36
|
+
.addClass(\"banner\")
|
37
|
+
.append(
|
38
|
+
`<i class=\"banner-text green-font material-icons\">done_all</i><h1>No Failures</>`
|
39
|
+
);
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
|
43
|
+
dataSource.forEach((feature, index) => {
|
44
|
+
$(\".features-grid\").append(
|
45
|
+
`<div class=\"module dark ${
|
46
|
+
feature.fail > 0 ? \"red-bg\" : \"\"
|
47
|
+
}\" onclick=\"showDetails(${index})\"><div class=\"funcname\"><h4>${
|
48
|
+
feature.name
|
49
|
+
}</h4></div><div class=\"total\"><h6>Total</h6><h4>${
|
50
|
+
feature.total
|
51
|
+
}</h4></div><div class=\"pass green-font\"><h6>Passed</h6><h4>${
|
52
|
+
feature.pass
|
53
|
+
}</h4></div><div class=\"fail red-font\"><h6>Failed</h6><h4>${
|
54
|
+
feature.fail
|
55
|
+
}</h4></div></div>`
|
56
|
+
);
|
57
|
+
});
|
58
|
+
}
|
59
|
+
|
60
|
+
function setFilter() {
|
61
|
+
if (displayFailuresOnly) {
|
62
|
+
$(\"#filter h5\").text(\"Failed\");
|
63
|
+
dataSource = allFeatures.filter((feature) => {
|
64
|
+
return feature.fail > 0;
|
65
|
+
});
|
66
|
+
} else {
|
67
|
+
$(\"#filter h5\").text(\"All\");
|
68
|
+
dataSource = allFeatures;
|
69
|
+
}
|
70
|
+
updateView();
|
71
|
+
displayFailuresOnly = !displayFailuresOnly;
|
72
|
+
}
|
73
|
+
|
74
|
+
function filterAllFailed() {
|
75
|
+
allFailedTests = [];
|
76
|
+
catergories = [];
|
77
|
+
|
78
|
+
failedFeatures = allFeatures.filter((feature) => {
|
79
|
+
return feature.fail > 0;
|
80
|
+
});
|
81
|
+
|
82
|
+
for (index = 0; index < failedFeatures.length; index++) {
|
83
|
+
failedFeatures[index].tests.filter((test) => {
|
84
|
+
if (!test.testPass) {
|
85
|
+
allFailedTests.push(test);
|
86
|
+
}
|
87
|
+
});
|
88
|
+
}
|
89
|
+
|
90
|
+
$(\"#body-wrap\").css(\"overflow\", \"hidden\");
|
91
|
+
$(\"#sidebar-overlay\").css(\"overflow\", \"auto\");
|
92
|
+
$(\"#sidebar-overlay\").css(\"visibility\", \"visible\");
|
93
|
+
$(\"#sidebar-overlay\").css(\"margin-left\", \"40%\");
|
94
|
+
$(\"#sidebar\").css(\"width\", \"40%\");
|
95
|
+
$(\"#sidebar-title\").css(\"visibility\", \"visible\");
|
96
|
+
$(\"#sidebar-status\").css(\"visibility\", \"visible\");
|
97
|
+
$(\"#sidebar-title\").css(\"opacity\", \"1\");
|
98
|
+
$(\"#sidebar-status\").css(\"opacity\", \"1\");
|
99
|
+
$(\"#sidebar-catergories\").css(\"visibility\", \"visible\");
|
100
|
+
$(\"#sidebar-catergories\").css(\"opacity\", \"1\");
|
101
|
+
/* Update Test Information */
|
102
|
+
|
103
|
+
$(\"#sidebar-title\").text(\"Failed Tests\");
|
104
|
+
$(\"#sidebar-status\").text(STATUS.fail);
|
105
|
+
$(\"#sidebar-overlay-grid\").empty();
|
106
|
+
allFailedTests.forEach((test) => {
|
107
|
+
$(\"#sidebar-overlay-grid\").append(
|
108
|
+
`<div id=\"sidebar-overlay-test-info\" onclick=\"()=>{}\"><i class=\"${
|
109
|
+
test.testPass ? \"green-font\" : \"red-font\"
|
110
|
+
} material-icons\" style=\"font-size: 1em\">${
|
111
|
+
STATUS.fail
|
112
|
+
}</i> <h4 id=\"test-title\">${test.name}</h4><div><h4 id=\"test-execution-time\">${test.time} secs</h4></div>${
|
113
|
+
test.comments !== \"\"
|
114
|
+
? `<p id=\"error-message\">${test.comments}</p>`
|
115
|
+
: \"\"
|
116
|
+
}</div>`
|
117
|
+
);
|
118
|
+
categorize(test);
|
119
|
+
});
|
120
|
+
displayCategories();
|
121
|
+
}
|
122
|
+
|
123
|
+
function displayCategories() {
|
124
|
+
$(\"#sidebar-catergories\").empty();
|
125
|
+
if(catergories.length === 1) { return; }
|
126
|
+
catergories.forEach((cat) => {$(\"#sidebar-catergories\").append(`<div><h6>#${cat.name}</h6></div>`);});
|
127
|
+
}
|
128
|
+
|
129
|
+
function switchTheme() {
|
130
|
+
currentTheme = $(document.documentElement).attr(\"theme\");
|
131
|
+
$(document.documentElement).attr(\"theme\", currentTheme === \"dark\" ? \"light\" : \"dark\");
|
132
|
+
$(\"#theme-icon\").text(currentTheme === \"dark\" ? \"wb_sunny\" : \"brightness_2\");
|
133
|
+
}
|
134
|
+
|
135
|
+
function closeDetails(e) {
|
136
|
+
if (e.target.id === \"sidebar\" || e.target.id === \"sidebar-overlay\") {
|
137
|
+
$(\"#sidebar-catergories\").css(\"visibility\", \"hidden\");
|
138
|
+
$(\"#sidebar-catergories\").css(\"opacity\", \"0\");
|
139
|
+
$(\"#sidebar-title\").css(\"visibility\", \"hidden\");
|
140
|
+
$(\"#sidebar-status\").css(\"visibility\", \"hidden\");
|
141
|
+
$(\"#sidebar-title\").css(\"opacity\", \"0\");
|
142
|
+
$(\"#sidebar-status\").css(\"opacity\", \"0\");
|
143
|
+
$(\"#sidebar-overlay\").css(\"margin-left\", \"0\");
|
144
|
+
$(\"#sidebar-overlay\").css(\"visibility\", \"hidden\");
|
145
|
+
$(\"#sidebar\").css(\"width\", \"0\");
|
146
|
+
$(\"#body-wrap\").css(\"overflow\", \"auto\");
|
147
|
+
$(\"#sidebar-overlay\").css(\"overflow\", \"hidden\");
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
window
|
152
|
+
.matchMedia(\"(prefers-color-scheme: dark)\")
|
153
|
+
.addEventListener(\"change\", (e) => {
|
154
|
+
darkTheme = e.matches;
|
155
|
+
$(document.documentElement).attr(\"theme\", darkTheme ? \"dark\" : \"light\");
|
156
|
+
$(\"#theme-icon\").text(darkTheme ? \"brightness_2\" : \"wb_sunny\");
|
157
|
+
});
|
158
|
+
|
159
|
+
function showDetails(featureID) {
|
160
|
+
feature = dataSource[featureID];
|
161
|
+
catergories = [];
|
162
|
+
|
163
|
+
$(\"#body-wrap\").css(\"overflow\", \"hidden\");
|
164
|
+
$(\"#sidebar-overlay\").css(\"overflow\", \"auto\");
|
165
|
+
$(\"#sidebar-overlay\").css(\"visibility\", \"visible\");
|
166
|
+
$(\"#sidebar-overlay\").css(\"margin-left\", \"40%\");
|
167
|
+
$(\"#sidebar\").css(\"width\", \"40%\");
|
168
|
+
$(\"#sidebar-title\").css(\"visibility\", \"visible\");
|
169
|
+
$(\"#sidebar-status\").css(\"visibility\", \"visible\");
|
170
|
+
$(\"#sidebar-title\").css(\"opacity\", \"1\");
|
171
|
+
$(\"#sidebar-status\").css(\"opacity\", \"1\");
|
172
|
+
$(\"#sidebar-catergories\").css(\"visibility\", \"visible\");
|
173
|
+
$(\"#sidebar-catergories\").css(\"opacity\", \"1\");
|
174
|
+
/* Update Test Information */
|
175
|
+
|
176
|
+
$(\"#sidebar-title\").text(feature.name);
|
177
|
+
$(\"#sidebar-overlay-grid\").empty();
|
178
|
+
feature.tests.forEach((test) => {
|
179
|
+
$(\"#sidebar-overlay-grid\").append(
|
180
|
+
`<div id=\"sidebar-overlay-test-info\" onclick=\"()=>{}\"><i class=\"${
|
181
|
+
test.testPass ? \"green-font\" : \"red-font\"
|
182
|
+
} material-icons\" style=\"font-size: 1em\">${
|
183
|
+
test.testPass ? STATUS.pass : STATUS.fail
|
184
|
+
}</i> <h4 id=\"test-title\">${test.name}</h4><div><h4 id=\"test-execution-time\">${test.time} secs</h4></div>${
|
185
|
+
test.comments !== \"\"
|
186
|
+
? `<p id=\"error-message\">${test.comments}</p>`
|
187
|
+
: \"\"
|
188
|
+
}</div>`
|
189
|
+
);
|
190
|
+
categorize(test);
|
191
|
+
});
|
192
|
+
displayCategories();
|
193
|
+
|
194
|
+
for (index = 0; index < feature.tests.length; index++) {
|
195
|
+
if (!feature.tests[index].testPass) {
|
196
|
+
$(\"#sidebar-status\").text(STATUS.fail);
|
197
|
+
return;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
$(\"#sidebar-status\").text(STATUS.pass);
|
201
|
+
}
|
202
|
+
|
203
|
+
function categorize(test) {
|
204
|
+
if (test.tag === \"\") {
|
205
|
+
return;
|
206
|
+
}
|
207
|
+
if (!catergoryAdded(test.tag)) {
|
208
|
+
catergories.push({ name: test.tag.toLowerCase(), tests: [test] });
|
209
|
+
} else {
|
210
|
+
catergories[catergoryIndex(test.tag)].tests.push(test);
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
function catergoryAdded(category) {
|
215
|
+
for (var i = 0; i < catergories.length; i++) {
|
216
|
+
if (catergories[i].name === category.toLowerCase()) {
|
217
|
+
return true;
|
218
|
+
}
|
219
|
+
}
|
220
|
+
return false;
|
221
|
+
}
|
222
|
+
|
223
|
+
function catergoryIndex(category) {
|
224
|
+
for (var i = 0; i < catergories.length; i++) {
|
225
|
+
if (catergories[i].name === category.toLowerCase()) {
|
226
|
+
return i;
|
227
|
+
}
|
228
|
+
}
|
229
|
+
return 0;
|
230
|
+
}
|
231
|
+
</script>"
|
232
|
+
end
|
233
|
+
end
|
metadata
CHANGED
@@ -1,31 +1,63 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nxgreport
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Balabharathi Jayaraman
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
11
|
+
date: 2021-08-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: test-unit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Generate a beautiful emailable test report.
|
42
|
+
email:
|
43
|
+
- balabharathi.jayaraman@gmail.com
|
15
44
|
executables: []
|
16
45
|
extensions: []
|
17
46
|
extra_rdoc_files: []
|
18
47
|
files:
|
19
|
-
- lib/nxgcore.rb
|
20
|
-
- lib/nxgcss.rb
|
21
48
|
- lib/nxgreport.rb
|
49
|
+
- lib/nxgreport/nxgcore.rb
|
50
|
+
- lib/nxgreport/nxgcss.rb
|
51
|
+
- lib/nxgreport/nxghtml.rb
|
52
|
+
- lib/nxgreport/nxgjs.rb
|
53
|
+
- lib/nxgreport/version.rb
|
22
54
|
homepage: https://rubygemspec.org/gems/nxgreport
|
23
55
|
licenses:
|
24
56
|
- MIT
|
25
57
|
metadata:
|
26
58
|
homepage_uri: https://rubygemspec.org/gems/nxgreport
|
27
|
-
source_code_uri: https://github.com/
|
28
|
-
changelog_uri: https://github.com/
|
59
|
+
source_code_uri: https://github.com/iambalabharathi/nxgreport-ruby
|
60
|
+
changelog_uri: https://github.com/iambalabharathi/nxgreport-ruby/blob/master/CHANGELOG.md
|
29
61
|
post_install_message:
|
30
62
|
rdoc_options: []
|
31
63
|
require_paths:
|
@@ -41,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
73
|
- !ruby/object:Gem::Version
|
42
74
|
version: '0'
|
43
75
|
requirements: []
|
44
|
-
rubygems_version: 3.1
|
76
|
+
rubygems_version: 3.0.3.1
|
45
77
|
signing_key:
|
46
78
|
specification_version: 4
|
47
79
|
summary: Next Gen Report
|
data/lib/nxgcore.rb
DELETED
@@ -1,539 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'pry'
|
3
|
-
require 'json'
|
4
|
-
require 'nxgcss.rb'
|
5
|
-
|
6
|
-
class NxgCore
|
7
|
-
class NxgReport
|
8
|
-
|
9
|
-
include NxgCss
|
10
|
-
|
11
|
-
def initialize(data_provider)
|
12
|
-
@data_provider = data_provider
|
13
|
-
@data_provider[:pass] = 0
|
14
|
-
@data_provider[:fail] = 0
|
15
|
-
@data_provider[:total] = 0
|
16
|
-
end
|
17
|
-
|
18
|
-
def setup(location: "./NxgReport.html", title: "Features Summary")
|
19
|
-
@data_provider[:report_path] = location.empty? ? "./NxgReport.html" : location
|
20
|
-
folder_check()
|
21
|
-
@data_provider[:title] = title
|
22
|
-
@data_provider[:title_color] = ""
|
23
|
-
@data_provider[:open_on_completion] = false
|
24
|
-
@data_provider[:features] = Array.new()
|
25
|
-
@start_time = Time.now.to_f
|
26
|
-
end
|
27
|
-
|
28
|
-
def open_upon_execution(value: true)
|
29
|
-
return if !value
|
30
|
-
|
31
|
-
@data_provider[:open_on_completion] = value
|
32
|
-
end
|
33
|
-
|
34
|
-
def set_environment(name: "")
|
35
|
-
return if name.empty?()
|
36
|
-
|
37
|
-
@data_provider[:environment] = name
|
38
|
-
end
|
39
|
-
|
40
|
-
def set_app_version(no: "")
|
41
|
-
return if no.empty?()
|
42
|
-
|
43
|
-
version_no = no.downcase.gsub("app", "").gsub("version", "").strip
|
44
|
-
@data_provider[:app_version] = "App Version #{version_no}"
|
45
|
-
end
|
46
|
-
|
47
|
-
def set_release(name: "")
|
48
|
-
return if name.empty?()
|
49
|
-
|
50
|
-
@data_provider[:release_name] = name
|
51
|
-
end
|
52
|
-
|
53
|
-
def set_os(name: "")
|
54
|
-
return if name.empty?()
|
55
|
-
|
56
|
-
@data_provider[:os] = name
|
57
|
-
end
|
58
|
-
|
59
|
-
def set_device(name: "")
|
60
|
-
return if name.empty?()
|
61
|
-
|
62
|
-
@data_provider[:device] = name
|
63
|
-
end
|
64
|
-
|
65
|
-
def set_execution(date: "")
|
66
|
-
return if date.empty?()
|
67
|
-
|
68
|
-
@data_provider[:execution_date] = date
|
69
|
-
end
|
70
|
-
|
71
|
-
def log_test(feature_name: "", test_name:"", test_status: "", comments: "")
|
72
|
-
if feature_name.nil?() || feature_name.strip.empty?()
|
73
|
-
log("Feature name cannot be empty.")
|
74
|
-
return
|
75
|
-
end
|
76
|
-
|
77
|
-
if test_status.nil?() || test_status.strip.empty?()
|
78
|
-
log("Test status cannot be empty.")
|
79
|
-
return
|
80
|
-
end
|
81
|
-
|
82
|
-
if test_name.nil?() || test_name.strip.empty?()
|
83
|
-
log("Test name cannot be empty.")
|
84
|
-
return
|
85
|
-
end
|
86
|
-
|
87
|
-
f_name = feature_name.strip
|
88
|
-
t_name = test_name.strip
|
89
|
-
t_pass = test_status.strip.downcase.include?('pass') ? true : false
|
90
|
-
t_comments = comments.strip
|
91
|
-
|
92
|
-
if !feature_exists?(f_name)
|
93
|
-
new_feature = {
|
94
|
-
"name" => f_name,
|
95
|
-
"total" => 0,
|
96
|
-
"pass" => 0,
|
97
|
-
"fail" => 0,
|
98
|
-
"tests" => Array.new()
|
99
|
-
}
|
100
|
-
@data_provider[:features].push(new_feature)
|
101
|
-
end
|
102
|
-
|
103
|
-
update_feature(f_name, t_name, t_pass, t_comments)
|
104
|
-
@data_provider[:total] += 1
|
105
|
-
@data_provider[t_pass ? :pass : :fail] += 1
|
106
|
-
end
|
107
|
-
|
108
|
-
def build(execution_time: 0)
|
109
|
-
set_execution_time(execution_time)
|
110
|
-
write()
|
111
|
-
if @data_provider[:open_on_completion]
|
112
|
-
system("open #{@data_provider[:report_path]}") if File.file?(@data_provider[:report_path])
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# Private methods
|
117
|
-
|
118
|
-
def update_feature(f_name, t_name, t_pass, t_comments)
|
119
|
-
@data_provider[:features].each do |feature|
|
120
|
-
if feature["name"].eql?(f_name)
|
121
|
-
feature["total"]+=1
|
122
|
-
feature[t_pass ? "pass" : "fail"]+=1
|
123
|
-
feature["tests"].push({
|
124
|
-
"name" => t_name,
|
125
|
-
"testPass" => t_pass,
|
126
|
-
"comments" => t_comments
|
127
|
-
})
|
128
|
-
return
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def feature_exists?(feature_name)
|
134
|
-
@data_provider[:features].each do |feature|
|
135
|
-
return true if feature["name"].eql?(feature_name)
|
136
|
-
end
|
137
|
-
return false
|
138
|
-
end
|
139
|
-
|
140
|
-
def log(message)
|
141
|
-
puts("🤖- #{message}")
|
142
|
-
end
|
143
|
-
|
144
|
-
def folder_check()
|
145
|
-
folder = File.dirname(@data_provider[:report_path])
|
146
|
-
FileUtils.mkdir_p(folder) unless File.directory?(folder)
|
147
|
-
end
|
148
|
-
|
149
|
-
def clean()
|
150
|
-
File.delete(@data_provider[:report_path]) if File.file?(@data_provider[:report_path])
|
151
|
-
end
|
152
|
-
|
153
|
-
def write()
|
154
|
-
clean()
|
155
|
-
if @data_provider[:features].length == 0
|
156
|
-
log("No tests logged, cannot build empty report.")
|
157
|
-
return
|
158
|
-
end
|
159
|
-
template = File.new(@data_provider[:report_path], 'w')
|
160
|
-
template.puts("<html lang=\"en\">
|
161
|
-
#{head()}
|
162
|
-
#{body()}
|
163
|
-
#{javascript()}
|
164
|
-
</html>")
|
165
|
-
template.close()
|
166
|
-
end
|
167
|
-
|
168
|
-
def head()
|
169
|
-
"<head>
|
170
|
-
<meta charset=\"UTF-8\" />
|
171
|
-
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />
|
172
|
-
<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js\"></script>
|
173
|
-
<title>Home | #{@data_provider[:title]}</title>
|
174
|
-
#{google_fonts_link()}
|
175
|
-
#{icons_link()}
|
176
|
-
#{css(@data_provider)}
|
177
|
-
</head>"
|
178
|
-
end
|
179
|
-
|
180
|
-
def google_fonts_link()
|
181
|
-
"<link
|
182
|
-
href=\"https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,600;0,700;0,800;1,300;1,400;1,600;1,700;1,800&display=swap\"
|
183
|
-
rel=\"stylesheet\"
|
184
|
-
/>"
|
185
|
-
end
|
186
|
-
|
187
|
-
def icons_link()
|
188
|
-
"<link
|
189
|
-
href=\"https://fonts.googleapis.com/icon?family=Material+Icons\"
|
190
|
-
rel=\"stylesheet\"
|
191
|
-
/>"
|
192
|
-
end
|
193
|
-
|
194
|
-
def body()
|
195
|
-
"<body id=\"app\" onload=\"onRefresh()\">
|
196
|
-
<div id=\"sidebar\" onclick=\"closeDetails()\">
|
197
|
-
<div id=\"sidebar-div\">
|
198
|
-
<div id=\"sidebar-title-wrap\">
|
199
|
-
<h1 id=\"sidebar-title\">Title</h1>
|
200
|
-
|
201
|
-
<i class=\"material-icons\" id=\"sidebar-status\">check_circle</i>
|
202
|
-
</div>
|
203
|
-
</div>
|
204
|
-
</div>
|
205
|
-
<div id=\"sidebar-overlay\" onclick=\"closeDetails()\">
|
206
|
-
<div id=\"sidebar-overlay-grid\"></div>
|
207
|
-
</div>
|
208
|
-
<div id=\"body-wrap\">
|
209
|
-
#{header()}
|
210
|
-
#{config()}
|
211
|
-
#{features()}
|
212
|
-
#{footer()}
|
213
|
-
</div>
|
214
|
-
</body>"
|
215
|
-
end
|
216
|
-
|
217
|
-
def header()
|
218
|
-
"<div id=\"header\">
|
219
|
-
<h1 id=\"app-title\">#{@data_provider[:title]}</h1>
|
220
|
-
<div id=\"theme-wrap\">
|
221
|
-
<button id=\"theme-switch\" onclick=\"switchTheme()\">
|
222
|
-
<i class=\"material-icons\" id=\"theme-icon\">brightness_2</i>
|
223
|
-
</button>
|
224
|
-
</div>
|
225
|
-
</div>"
|
226
|
-
end
|
227
|
-
|
228
|
-
def features()
|
229
|
-
"<div class=\"features-grid\"></div>"
|
230
|
-
end
|
231
|
-
|
232
|
-
def features_js_array()
|
233
|
-
return @data_provider[:features].to_s.gsub("=>", ":")
|
234
|
-
end
|
235
|
-
|
236
|
-
def footer()
|
237
|
-
"<div id=\"footer\">
|
238
|
-
<p>
|
239
|
-
Developed by
|
240
|
-
<span>
|
241
|
-
<a
|
242
|
-
href=\"https://www.linkedin.com/in/balabharathijayaraman\"
|
243
|
-
rel=\"nofollow\"
|
244
|
-
target=\"_blank\"
|
245
|
-
>Balabharathi Jayaraman</a
|
246
|
-
>
|
247
|
-
</span>
|
248
|
-
</p>
|
249
|
-
</div>"
|
250
|
-
end
|
251
|
-
|
252
|
-
def javascript()
|
253
|
-
"<script>
|
254
|
-
var darkTheme = false;
|
255
|
-
var displayFailuresOnly = false;
|
256
|
-
|
257
|
-
const allFeatures = #{features_js_array};
|
258
|
-
|
259
|
-
var dataSource = [];
|
260
|
-
|
261
|
-
const STATUS = {
|
262
|
-
pass: \"check_circle\",
|
263
|
-
fail: \"cancel\",
|
264
|
-
};
|
265
|
-
|
266
|
-
function onRefresh() {
|
267
|
-
switchTheme();
|
268
|
-
dataSource = allFeatures;
|
269
|
-
setFilter();
|
270
|
-
}
|
271
|
-
|
272
|
-
function updateView() {
|
273
|
-
$(\".banner\").removeClass(\"banner\").addClass(\"features-grid\");
|
274
|
-
$(\".features-grid\").empty();
|
275
|
-
|
276
|
-
if (dataSource.length === 0) {
|
277
|
-
console.log(\"inside\");
|
278
|
-
$(\".features-grid\")
|
279
|
-
.removeClass(\"features-grid\")
|
280
|
-
.addClass(\"banner\")
|
281
|
-
.append(
|
282
|
-
`<i class=\"banner-text green-font material-icons\">done_all</i><h1>No Failures</>`
|
283
|
-
);
|
284
|
-
return;
|
285
|
-
}
|
286
|
-
|
287
|
-
dataSource.forEach((feature, index) => {
|
288
|
-
$(\".features-grid\").append(
|
289
|
-
`<div class=\"module dark ${
|
290
|
-
feature.fail > 0 ? \"red-bg\" : \"\"
|
291
|
-
}\" onclick=\"showDetails(${index})\"><div class=\"funcname\"><h4>${
|
292
|
-
feature.name
|
293
|
-
}</h4></div><div class=\"total\"><h6>Total</h6><h4>${
|
294
|
-
feature.total
|
295
|
-
}</h4></div><div class=\"pass green-font\"><h6>Passed</h6><h4>${
|
296
|
-
feature.pass
|
297
|
-
}</h4></div><div class=\"fail red-font\"><h6>Failed</h6><h4>${
|
298
|
-
feature.fail
|
299
|
-
}</h4></div></div>`
|
300
|
-
);
|
301
|
-
});
|
302
|
-
}
|
303
|
-
|
304
|
-
function setFilter() {
|
305
|
-
if (displayFailuresOnly) {
|
306
|
-
$(\"#filter h5\").text(\"Failed\");
|
307
|
-
dataSource = allFeatures.filter((feature) => {
|
308
|
-
return feature.fail > 0;
|
309
|
-
});
|
310
|
-
} else {
|
311
|
-
$(\"#filter h5\").text(\"All\");
|
312
|
-
dataSource = allFeatures;
|
313
|
-
}
|
314
|
-
updateView();
|
315
|
-
displayFailuresOnly = !displayFailuresOnly;
|
316
|
-
}
|
317
|
-
|
318
|
-
function filterAllFailed() {
|
319
|
-
allFailedTests = [];
|
320
|
-
|
321
|
-
failedFeatures = allFeatures.filter((feature) => {
|
322
|
-
return feature.fail > 0;
|
323
|
-
});
|
324
|
-
|
325
|
-
for (index = 0; index < failedFeatures.length; index++) {
|
326
|
-
failedFeatures[index].tests.filter((test) => {
|
327
|
-
if (!test.testPass) {
|
328
|
-
allFailedTests.push(test);
|
329
|
-
}
|
330
|
-
});
|
331
|
-
}
|
332
|
-
|
333
|
-
$(\"#sidebar-overlay\").css(\"visibility\", \"visible\");
|
334
|
-
$(\"#sidebar-overlay\").css(\"margin-left\", \"40%\");
|
335
|
-
$(\"#sidebar\").css(\"width\", \"40%\");
|
336
|
-
$(\"#sidebar-title\").css(\"visibility\", \"visible\");
|
337
|
-
$(\"#sidebar-status\").css(\"visibility\", \"visible\");
|
338
|
-
/* Update Test Information */
|
339
|
-
|
340
|
-
$(\"#sidebar-title\").text(\"Failed Tests\");
|
341
|
-
$(\"#sidebar-status\").text(STATUS.fail);
|
342
|
-
$(\"#sidebar-overlay-grid\").empty();
|
343
|
-
allFailedTests.forEach((test) => {
|
344
|
-
$(\"#sidebar-overlay-grid\").append(
|
345
|
-
`<div id=\"sidebar-overlay-test-info\" onclick=\"()=>{}\"><i class=\"${
|
346
|
-
test.testPass ? \"green-font\" : \"red-font\"
|
347
|
-
} material-icons\" style=\"font-size: 1em\">${
|
348
|
-
STATUS.fail
|
349
|
-
}</i> <h4 id=\"test-title\">${test.name}</h4>${
|
350
|
-
test.comments !== \"\"
|
351
|
-
? `<p id=\"error-message\">${test.comments}</p>`
|
352
|
-
: \"\"
|
353
|
-
}</div>`
|
354
|
-
);
|
355
|
-
});
|
356
|
-
}
|
357
|
-
|
358
|
-
function switchTheme() {
|
359
|
-
$(document.documentElement).attr(\"theme\", !darkTheme ? \"light\" : \"dark\");
|
360
|
-
$(\"#theme-icon\").text(!darkTheme ? \"wb_sunny\" : \"brightness_2\");
|
361
|
-
darkTheme = !darkTheme;
|
362
|
-
}
|
363
|
-
|
364
|
-
function closeDetails() {
|
365
|
-
$(\"#sidebar-title\").css(\"visibility\", \"hidden\");
|
366
|
-
$(\"#sidebar-status\").css(\"visibility\", \"hidden\");
|
367
|
-
$(\"#sidebar-overlay\").css(\"visibility\", \"hidden\");
|
368
|
-
$(\"#sidebar-overlay\").css(\"margin-left\", \"0\");
|
369
|
-
$(\"#sidebar\").css(\"width\", \"0\");
|
370
|
-
}
|
371
|
-
|
372
|
-
window
|
373
|
-
.matchMedia(\"(prefers-color-scheme: dark)\")
|
374
|
-
.addEventListener(\"change\", (e) => {
|
375
|
-
darkTheme = e.matches;
|
376
|
-
switchTheme();
|
377
|
-
});
|
378
|
-
|
379
|
-
function showDetails(featureID) {
|
380
|
-
feature = dataSource[featureID];
|
381
|
-
|
382
|
-
$(\"#sidebar-overlay\").css(\"visibility\", \"visible\");
|
383
|
-
$(\"#sidebar-overlay\").css(\"margin-left\", \"40%\");
|
384
|
-
$(\"#sidebar\").css(\"width\", \"40%\");
|
385
|
-
$(\"#sidebar-title\").css(\"visibility\", \"visible\");
|
386
|
-
$(\"#sidebar-status\").css(\"visibility\", \"visible\");
|
387
|
-
/* Update Test Information */
|
388
|
-
|
389
|
-
$(\"#sidebar-title\").text(feature.name);
|
390
|
-
$(\"#sidebar-overlay-grid\").empty();
|
391
|
-
feature.tests.forEach((test) => {
|
392
|
-
$(\"#sidebar-overlay-grid\").append(
|
393
|
-
`<div id=\"sidebar-overlay-test-info\" onclick=\"()=>{}\"><i class=\"${
|
394
|
-
test.testPass ? \"green-font\" : \"red-font\"
|
395
|
-
} material-icons\" style=\"font-size: 1em\">${
|
396
|
-
test.testPass ? STATUS.pass : STATUS.fail
|
397
|
-
}</i> <h4 id=\"test-title\">${test.name}</h4>${
|
398
|
-
test.comments !== \"\"
|
399
|
-
? `<p id=\"error-message\">${test.comments}</p>`
|
400
|
-
: \"\"
|
401
|
-
}</div>`
|
402
|
-
);
|
403
|
-
});
|
404
|
-
|
405
|
-
for (index = 0; index < feature.tests.length; index++) {
|
406
|
-
if (!feature.tests[index].testPass) {
|
407
|
-
$(\"#sidebar-status\").text(STATUS.fail);
|
408
|
-
return;
|
409
|
-
}
|
410
|
-
}
|
411
|
-
$(\"#sidebar-status\").text(STATUS.pass);
|
412
|
-
}
|
413
|
-
|
414
|
-
</script>"
|
415
|
-
end
|
416
|
-
|
417
|
-
def config()
|
418
|
-
return if @data_provider.length == 0
|
419
|
-
|
420
|
-
return "<div class=\"params-container\">
|
421
|
-
#{release_name()}
|
422
|
-
#{execution_date()}
|
423
|
-
#{device()}
|
424
|
-
#{os()}
|
425
|
-
#{app_version()}
|
426
|
-
#{environment()}
|
427
|
-
#{passed_tests()}
|
428
|
-
#{failed_tests()}
|
429
|
-
#{percentage_pass()}
|
430
|
-
#{execution_time()}
|
431
|
-
#{filter()}
|
432
|
-
</div>"
|
433
|
-
end
|
434
|
-
|
435
|
-
def execution_time()
|
436
|
-
return if !@data_provider.key?(:environment)
|
437
|
-
|
438
|
-
return config_item("Total execution time", @data_provider[:execution_time],'access_time')
|
439
|
-
end
|
440
|
-
|
441
|
-
def filter()
|
442
|
-
"<div class=\"param-wrap\" onclick=\"setFilter()\" id=\"filter\" title=\"Filter tests\">
|
443
|
-
<i class=\"pi material-icons\">filter_list</i>
|
444
|
-
<h5 id=\"pt\">Failed</h5>
|
445
|
-
</div>"
|
446
|
-
end
|
447
|
-
|
448
|
-
def passed_tests()
|
449
|
-
"<div class=\"param-wrap\" title=\"Passed tests\">
|
450
|
-
<i class=\"pi green-font material-icons\">check_circle</i>
|
451
|
-
<h5 id=\"pt\">#{@data_provider[:pass] == 0 ? "None" : @data_provider[:pass]}</h5>
|
452
|
-
</div>"
|
453
|
-
end
|
454
|
-
|
455
|
-
def failed_tests()
|
456
|
-
"<div class=\"param-wrap\" title=\"Failed tests\" #{@data_provider[:fail] > 0 ? "onclick=\"filterAllFailed()\" style=\"cursor: pointer\"" : ""}>
|
457
|
-
<i class=\"pi red-font material-icons\">cancel</i>
|
458
|
-
<h5 id=\"pt\">#{@data_provider[:fail] == 0 ? "None" : @data_provider[:fail]}</h5>
|
459
|
-
</div>"
|
460
|
-
end
|
461
|
-
|
462
|
-
def percentage_pass()
|
463
|
-
pass_percentage = ((@data_provider[:pass]/@data_provider[:total].to_f) * 100).round(2)
|
464
|
-
|
465
|
-
return config_item("Pass percentage", pass_percentage,'equalizer')
|
466
|
-
end
|
467
|
-
|
468
|
-
def environment()
|
469
|
-
return if !@data_provider.key?(:environment)
|
470
|
-
|
471
|
-
return config_item("Test environment", @data_provider[:environment], "layers")
|
472
|
-
end
|
473
|
-
|
474
|
-
def app_version()
|
475
|
-
return if !@data_provider.key?(:app_version)
|
476
|
-
|
477
|
-
return config_item("App version tested", @data_provider[:app_version], "info")
|
478
|
-
end
|
479
|
-
|
480
|
-
def release_name()
|
481
|
-
return if !@data_provider.key?(:release_name)
|
482
|
-
|
483
|
-
return config_item("Release", @data_provider[:release_name], "bookmark")
|
484
|
-
end
|
485
|
-
|
486
|
-
def os()
|
487
|
-
return if !@data_provider.key?(:os)
|
488
|
-
|
489
|
-
return config_item("Os tested", @data_provider[:os], "settings")
|
490
|
-
end
|
491
|
-
|
492
|
-
def device()
|
493
|
-
return if !@data_provider.key?(:device)
|
494
|
-
|
495
|
-
return config_item("Device tested", @data_provider[:device], "devices")
|
496
|
-
end
|
497
|
-
|
498
|
-
def execution_date()
|
499
|
-
@data_provider[:execution_date] = Time.now().strftime("%b %d, %Y") if !@data_provider.key?(:execution_date)
|
500
|
-
|
501
|
-
return config_item("Execution date", @data_provider[:execution_date], "event")
|
502
|
-
end
|
503
|
-
|
504
|
-
def config_item(toot_tip, name, icon)
|
505
|
-
"<div class=\"param-wrap\" title=\"#{toot_tip}\">
|
506
|
-
<i class=\"pi material-icons\">#{icon}</i>
|
507
|
-
<h5 id=\"pt\">#{name}</h5>
|
508
|
-
</div>"
|
509
|
-
end
|
510
|
-
|
511
|
-
def set_execution_time(time)
|
512
|
-
time_diff_in_mins = 0
|
513
|
-
if time == 0
|
514
|
-
@end_time = Time.now.to_f
|
515
|
-
time_diff_in_mins = ((@end_time - @start_time) / 60).to_i
|
516
|
-
else
|
517
|
-
time_diff_in_mins = (time / 60).to_i
|
518
|
-
end
|
519
|
-
|
520
|
-
if time_diff_in_mins >= 60
|
521
|
-
time_diff_in_hrs = (time_diff_in_mins / 60.to_f).round(2)
|
522
|
-
@data_provider[:execution_time] = "#{time_diff_in_hrs} #{time_diff_in_hrs == 1 ? "hour" : "hours"}"
|
523
|
-
else
|
524
|
-
@data_provider[:execution_time] = "#{time_diff_in_mins} mins"
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
|
-
private :log, :clean, :write
|
529
|
-
private :execution_date, :device, :os, :release_name, :app_version, :environment
|
530
|
-
private :features, :config, :config_item, :features_js_array
|
531
|
-
private :head, :body, :header, :footer, :javascript
|
532
|
-
end
|
533
|
-
|
534
|
-
private_constant :NxgReport
|
535
|
-
|
536
|
-
def instance(data_provider: Hash.new())
|
537
|
-
NxgReport.new(data_provider)
|
538
|
-
end
|
539
|
-
end
|