nxgreport 0.8.0 → 0.11.2

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.
data/lib/nxgcore.rb DELETED
@@ -1,420 +0,0 @@
1
- require 'fileutils'
2
-
3
- require 'nxgcss.rb'
4
-
5
- class NxgCore
6
- class NxgReport
7
-
8
- include NxgCss
9
-
10
- def initialize(data_provider)
11
- @data_provider = data_provider
12
- @data_provider[:pass] = 0
13
- @data_provider[:fail] = 0
14
- @data_provider[:total] = 0
15
- end
16
-
17
- def setup(location: "./NxgReport.html", title: "Features Summary")
18
- @data_provider[:report_path] = location.empty? ? "./NxgReport.html" : location
19
- folder_check()
20
- @data_provider[:title] = title
21
- @data_provider[:title_color] = "background: linear-gradient(to bottom right, #ff644e, #cb3018);"
22
- @data_provider[:open_on_completion] = false
23
- @data_provider[:features] = Hash.new()
24
- @start_time = Time.now.to_f
25
- end
26
-
27
- def set_title_color(hex_color: "")
28
- if hex_color.strip().empty?() || hex_color.strip()[0] != "#"
29
- log("set_title_color method is called with empty color. please check the code.")
30
- return
31
- end
32
- @data_provider[:title_color] = "background-color: #{hex_color.strip().downcase()};"
33
- end
34
-
35
- def open_upon_execution(value: true)
36
- return if !value
37
-
38
- @data_provider[:open_on_completion] = value
39
- end
40
-
41
- def set_environment(name: "")
42
- return if name.empty?()
43
-
44
- @data_provider[:environment] = name
45
- end
46
-
47
- def set_app_version(no: "")
48
- return if no.empty?()
49
-
50
- version_no = no.downcase.gsub("app", "").gsub("version", "").strip
51
- @data_provider[:app_version] = "App Version #{version_no}"
52
- end
53
-
54
- def set_release(name: "")
55
- return if name.empty?()
56
-
57
- @data_provider[:release_name] = name
58
- end
59
-
60
- def set_os(name: "")
61
- return if name.empty?()
62
-
63
- @data_provider[:os] = name
64
- end
65
-
66
- def set_device(name: "")
67
- return if name.empty?()
68
-
69
- @data_provider[:device] = name
70
- end
71
-
72
- def set_execution(date: "")
73
- return if date.empty?()
74
-
75
- @data_provider[:execution_date] = date
76
- end
77
-
78
- def log_test(feature_name: "", test_status: "")
79
- if feature_name.nil?() || feature_name.strip.empty?()
80
- log("Feature name cannot be empty.")
81
- return
82
- end
83
-
84
- if test_status.nil?() || test_status.strip.empty?()
85
- log("Test status cannot be empty.")
86
- return
87
- end
88
-
89
- test_pass = test_status.downcase.include?('pass')
90
- name = feature_name.strip()
91
-
92
- if !@data_provider[:features].key?(name)
93
- @data_provider[:features][name]=[0,0,0]
94
- end
95
-
96
- @data_provider[:features][name][0]+=1
97
- @data_provider[:total]+=1
98
- @data_provider[:features][name][(test_pass) ? 1 : 2]+=1
99
- @data_provider[(test_pass) ? :pass : :fail]+=1
100
- end
101
-
102
- def build(execution_time: 0)
103
- set_execution_time(execution_time)
104
- write()
105
- if @data_provider[:open_on_completion]
106
- system("open #{@data_provider[:report_path]}") if File.file?(@data_provider[:report_path])
107
- end
108
- end
109
-
110
- # Private methods
111
- def log(message)
112
- puts("🤖- #{message}")
113
- end
114
-
115
- def folder_check()
116
- folder = File.dirname(@data_provider[:report_path])
117
- FileUtils.mkdir_p(folder) unless File.directory?(folder)
118
- end
119
-
120
- def clean()
121
- File.delete(@data_provider[:report_path]) if File.file?(@data_provider[:report_path])
122
- end
123
-
124
- def write()
125
- clean()
126
- if @data_provider[:features].length == 0
127
- log("No tests logged, cannot build empty report.")
128
- return
129
- end
130
- template = File.new(@data_provider[:report_path], 'w')
131
- template.puts("<html lang=\"en\">
132
- #{head()}
133
- #{body()}
134
- #{javascript()}
135
- </html>")
136
- template.close()
137
- end
138
-
139
- def head()
140
- "<head>
141
- <meta charset=\"UTF-8\" />
142
- <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />
143
- <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js\"></script>
144
- <title>Home | #{@data_provider[:title]}</title>
145
- #{google_fonts_link()}
146
- #{icons_link()}
147
- #{css(@data_provider)}
148
- </head>"
149
- end
150
-
151
- def google_fonts_link()
152
- "<link
153
- 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\"
154
- rel=\"stylesheet\"
155
- />"
156
- end
157
-
158
- def icons_link()
159
- "<link
160
- href=\"https://fonts.googleapis.com/icon?family=Material+Icons\"
161
- rel=\"stylesheet\"
162
- />"
163
- end
164
-
165
- def body()
166
- "<body class=\"dark\" id=\"app\" onload=\"onStart()\">
167
- <div class=\"body-wrapper\">
168
- #{header()}
169
- #{config()}
170
- #{features()}
171
- #{footer()}
172
- </div>
173
- </body>"
174
- end
175
-
176
- def header()
177
- "<div class=\"header\">
178
- <h1>#{@data_provider[:title]}</h1>
179
- <div class=\"button-wrapper\">
180
- <button id=\"theme-switch\" onclick=\"handleThemeSwitch()\">
181
- <i class=\"material-icons\" id=\"theme-switch-icon\">brightness_2</i>
182
- </button>
183
- </div>
184
- </div>"
185
- end
186
-
187
- def features()
188
- "<div class=\"mc\"></div>"
189
- end
190
-
191
- def features_js_array()
192
- js_array = ''
193
- @data_provider[:features].each do |name, metrics|
194
- js_array += "{ name: \"#{name}\", total: #{metrics[0]}, pass: #{metrics[1]}, fail: #{metrics[2]} },"
195
- end
196
- return js_array
197
- end
198
-
199
- def footer()
200
- "<div class=\"footer\">
201
- <p>
202
- Developed by
203
- <span>
204
- <a
205
- href=\"https://www.linkedin.com/in/balabharathijayaraman\"
206
- rel=\"nofollow\"
207
- target=\"_blank\"
208
- >Balabharathi Jayaraman</a
209
- >
210
- </span>
211
- </p>
212
- </div>"
213
- end
214
-
215
- def javascript()
216
- "<script>
217
- var theme = \"dark\";
218
- var displayAllTests = true;
219
-
220
- var features = [
221
- #{features_js_array()}
222
- ]
223
-
224
- function onStart() {
225
- displayAll();
226
- }
227
-
228
- function handleThemeSwitch() {
229
- if (theme === \"dark\") {
230
- theme = \"light\";
231
- document.getElementById(\"app\").classList.remove(\"dark\");
232
- document.getElementById(\"theme-switch-icon\").innerHTML = \"wb_sunny\";
233
- document.getElementById(\"theme-switch-icon\");
234
- return;
235
- }
236
- if (theme === \"light\") {
237
- theme = \"dark\";
238
- document.getElementById(\"app\").classList.add(\"dark\");
239
- document.getElementById(\"theme-switch-icon\").innerHTML = \"brightness_2\";
240
- }
241
- }
242
-
243
- function handleFilter() {
244
- displayAllTests = !displayAllTests;
245
- if (displayAllTests) {
246
- displayAll();
247
- } else {
248
- displayFailuresOnly();
249
- }
250
- }
251
-
252
- function displayAll() {
253
- $(\"#filter h5\").text(\"All\");
254
- $(\".banner-in-the-middle\").removeClass(\"banner-in-the-middle\").addClass(\"mc\");
255
- $(\".mc\").empty();
256
- features.forEach((item) => {
257
- $(\".mc\").append(
258
- `<div class=\"module dark ${
259
- item.fail > 0 ? \"danger\" : \"\"
260
- }\"><div class=\"funcname\"><h4>${
261
- item.name
262
- }</h4></div><div class=\"total\"><h6>Total</h6><h4>${
263
- item.total
264
- }</h4></div><div class=\"pass\"><h6>Passed</h6><h4>${
265
- item.pass
266
- }</h4></div><div class=\"fail\"><h6>Failed</h6><h4>${
267
- item.fail
268
- }</h4></div></div>`
269
- );
270
- });
271
- }
272
-
273
- function displayFailuresOnly() {
274
- $(\"#filter h5\").text(\"Failures\");
275
- $(\".banner-in-the-middle\").removeClass(\"banner-in-the-middle\").addClass(\"mc\");
276
- $(\".mc\").empty();
277
- failureCount = 0;
278
- features.forEach((item) => {
279
- if (item.fail > 0) {
280
- failureCount++;
281
- $(\".mc\").append(
282
- `<div class=\"module dark danger\"><div class=\"funcname\"><h4>${item.name}</h4></div><div class=\"total\"><h6>Total</h6><h4>${item.total}</h4></div><div class=\"pass\"><h6>Passed</h6><h4>${item.pass}</h4></div><div class=\"fail\"><h6>Failed</h6><h4>${item.fail}</h4></div></div>`
283
- );
284
- }
285
- });
286
- if (failureCount === 0) {
287
- $(\".mc\")
288
- .removeClass(\"mc\")
289
- .addClass(\"banner-in-the-middle\")
290
- .append(
291
- `<i class=\"banner-text material-icons\">done_all</i><h1>No Failures</>`
292
- );
293
- }
294
- }
295
- </script>"
296
- end
297
-
298
- def config()
299
- return if @data_provider.length == 0
300
-
301
- return "<div class=\"configuration-container\">
302
- #{release_name()}
303
- #{execution_date()}
304
- #{device()}
305
- #{os()}
306
- #{app_version()}
307
- #{environment()}
308
- #{passed_tests()}
309
- #{failed_tests()}
310
- #{percentage_pass()}
311
- #{execution_time()}
312
- #{filter()}
313
- </div>"
314
- end
315
-
316
- def execution_time()
317
- return if !@data_provider.key?(:environment)
318
-
319
- return config_item("Total execution time", @data_provider[:execution_time],'access_time')
320
- end
321
-
322
- def filter()
323
- "<div class=\"configuration-wrapper\" onclick=\"handleFilter()\" id=\"filter\" title=\"Filter tests\">
324
- <i class=\"configuration-icon material-icons\">filter_list</i>
325
- <h5 id=\"configuration-text\">Failed</h5>
326
- </div>"
327
- end
328
-
329
- def passed_tests()
330
- "<div class=\"configuration-wrapper\" title=\"Passed tests\">
331
- <i class=\"configuration-icon pass-total material-icons\">check_circle</i>
332
- <h5 id=\"configuration-text\">#{@data_provider[:pass] == 0 ? "None" : @data_provider[:pass]}</h5>
333
- </div>"
334
- end
335
-
336
- def failed_tests()
337
- "<div class=\"configuration-wrapper\" title=\"Failed tests\">
338
- <i class=\"configuration-icon fail-total material-icons\">cancel</i>
339
- <h5 id=\"configuration-text\">#{@data_provider[:fail] == 0 ? "None" : @data_provider[:fail]}</h5>
340
- </div>"
341
- end
342
-
343
- def percentage_pass()
344
- pass_percentage = ((@data_provider[:pass]/@data_provider[:total].to_f) * 100).round(2)
345
-
346
- return config_item("Pass percentage", pass_percentage,'equalizer')
347
- end
348
-
349
- def environment()
350
- return if !@data_provider.key?(:environment)
351
-
352
- return config_item("Test environment", @data_provider[:environment], "layers")
353
- end
354
-
355
- def app_version()
356
- return if !@data_provider.key?(:app_version)
357
-
358
- return config_item("App version tested", @data_provider[:app_version], "info")
359
- end
360
-
361
- def release_name()
362
- return if !@data_provider.key?(:release_name)
363
-
364
- return config_item("Release", @data_provider[:release_name], "bookmark")
365
- end
366
-
367
- def os()
368
- return if !@data_provider.key?(:os)
369
-
370
- return config_item("Os tested", @data_provider[:os], "settings")
371
- end
372
-
373
- def device()
374
- return if !@data_provider.key?(:device)
375
-
376
- return config_item("Device tested", @data_provider[:device], "devices")
377
- end
378
-
379
- def execution_date()
380
- @data_provider[:execution_date] = Time.now().strftime("%b %d, %Y") if !@data_provider.key?(:execution_date)
381
-
382
- return config_item("Execution date", @data_provider[:execution_date], "event")
383
- end
384
-
385
- def config_item(toot_tip, name, icon)
386
- "<div class=\"configuration-wrapper\" title=\"#{toot_tip}\">
387
- <i class=\"configuration-icon material-icons\">#{icon}</i>
388
- <h5 id=\"configuration-text\">#{name}</h5>
389
- </div>"
390
- end
391
-
392
- def set_execution_time(time)
393
- time_diff_in_mins = 0
394
- if time == 0
395
- @end_time = Time.now.to_f
396
- time_diff_in_mins = ((@end_time - @start_time) / 60).to_i
397
- else
398
- time_diff_in_mins = (time / 60).to_i
399
- end
400
-
401
- if time_diff_in_mins >= 60
402
- time_diff_in_hrs = (time_diff_in_mins / 60.to_f).round(2)
403
- @data_provider[:execution_time] = "#{time_diff_in_hrs} #{time_diff_in_hrs == 1 ? "hour" : "hours"}"
404
- else
405
- @data_provider[:execution_time] = "#{time_diff_in_mins} mins"
406
- end
407
- end
408
-
409
- private :log, :clean, :write
410
- private :execution_date, :device, :os, :release_name, :app_version, :environment
411
- private :features, :config, :config_item, :features_js_array
412
- private :head, :body, :header, :footer, :javascript
413
- end
414
-
415
- private_constant :NxgReport
416
-
417
- def instance(data_provider: Hash.new())
418
- NxgReport.new(data_provider)
419
- end
420
- end
data/lib/nxgcss.rb DELETED
@@ -1,335 +0,0 @@
1
-
2
- module NxgCss
3
-
4
- def has_environment_settings(data_provider)
5
- data_provider.key?(:environment) || data_provider.key?(:app_version) || data_provider.key?(:release_name) || data_provider.key?(:os) || data_provider.key?(:device) || data_provider.key?(:execution_date)
6
- end
7
-
8
- def css(data_provider)
9
- "<style>
10
- :root {
11
- --dark-bg: rgb(41, 40, 40);
12
- --dark-primary: #050505;
13
- --dark-secondary: #050505a9;
14
- --dark-font: rgb(201, 201, 201);
15
- --dark-blue: rgb(0, 225, 255);
16
- --dark-green: rgba(115, 255, 0, 0.89);
17
- --dark-red: rgb(255, 0, 0);
18
- --dark-shadow: rgba(0, 0, 0, 0.5);
19
-
20
- --light-bg: rgb(226, 226, 226);
21
- --light-primary: #fff;
22
- --light-secondary: rgba(255, 255, 255, 0.445);
23
- --light-font: rgb(44, 44, 44);
24
- --light-blue: rgb(1, 67, 165);
25
- --light-green: rgb(14, 138, 2);
26
- --light-red: rgb(255, 0, 0);
27
- --light-shadow: rgba(245, 245, 245, 0.5);
28
-
29
- --font: \"Open Sans\", sans-serif;
30
- --danger-bg: rgba(255, 0, 0, 0.185);
31
- --color-switch-animation: all 500ms ease;
32
- }
33
-
34
- body {
35
- font-family: var(--font);
36
- margin: auto;
37
- transition: var(--color-switch-animation);
38
- }
39
-
40
- .body-wrapper {
41
- display: grid;
42
- grid-template-rows: auto auto 1fr;
43
- height: 100vh;
44
- width: 100vw;
45
- }
46
-
47
- .header {
48
- display: grid;
49
- grid-template-columns: 8fr 1fr;
50
- text-align: center;
51
- #{data_provider[:title_color]}
52
- }
53
-
54
- .configuration-container {
55
- display: flex;
56
- flex-wrap: wrap;
57
- justify-content: space-between;
58
- text-align: center;
59
- padding: 1.5em 2em 1em 2em;
60
- }
61
-
62
- .configuration-wrapper {
63
- display: flex;
64
- place-items: center;
65
- }
66
-
67
- .configuration-icon {
68
- font-size: 1.5em;
69
- padding-right: 0.5em;
70
- }
71
-
72
- #configuration-text {
73
- font-size: 0.85em;
74
- }
75
-
76
- #filter {
77
- cursor: pointer;
78
- border-radius: 1em;
79
- width: 6em;
80
- padding: 0.2em 0.8em;
81
- background-color: var(--light-secondary);
82
- -webkit-box-shadow: -1px 0px 5px 0px var(--light-shadow);
83
- -moz-box-shadow: -1px 0px 5px 0px var(--light-shadow);
84
- box-shadow: -1px 0px 5px 0px var(--light-shadow);
85
- }
86
-
87
- .mc {
88
- display: grid;
89
- grid-template-columns: 1fr 1fr 1fr;
90
- grid-auto-rows: 70px;
91
- grid-gap: 0.5em;
92
- padding: 0.5em 2em;
93
- }
94
-
95
- .banner-in-the-middle {
96
- text-align: center;
97
- margin: auto;
98
- }
99
-
100
- .banner-text {
101
- color: green;
102
- font-size: 5em;
103
- }
104
-
105
- .banner-in-the-middle > h1 {
106
- color: var(--light-font);
107
- }
108
-
109
- .footer {
110
- margin-bottom: 0.5em;
111
- padding: 3em 3em 1em 3em;
112
- text-align: center;
113
- font-size: 0.7rem;
114
- font-weight: 600;
115
- }
116
-
117
- a {
118
- cursor: pointer;
119
- font-weight: 600;
120
- }
121
-
122
- .module {
123
- display: grid;
124
- place-items: center;
125
- grid-template-columns: 3fr 1fr 1fr 1fr;
126
- border-radius: 0.7rem;
127
- padding: 10px 10px;
128
- -webkit-box-shadow: -1px 0px 5px 0px var(--light-shadow);
129
- -moz-box-shadow: -1px 0px 5px 0px var(--light-shadow);
130
- box-shadow: -1px 0px 5px 0px var(--light-shadow);
131
- }
132
-
133
- .button-body-wrapper {
134
- place-items: center;
135
- }
136
-
137
- #theme-switch {
138
- width: 5em;
139
- height: 5em;
140
- background-color: Transparent;
141
- background-repeat: no-repeat;
142
- border: none;
143
- cursor: pointer;
144
- overflow: hidden;
145
- outline: none;
146
- margin: 0;
147
- margin-right: 1em;
148
- position: relative;
149
- top: 50%;
150
- -ms-transform: translateY(-50%);
151
- transform: translateY(-50%);
152
- }
153
-
154
- h2,
155
- h3,
156
- h4,
157
- h5,
158
- h6 {
159
- text-align: center;
160
- margin: auto;
161
- }
162
-
163
- .total,
164
- .pass,
165
- .fail {
166
- display: grid;
167
- width: 100%;
168
- height: 100%;
169
- place-items: center;
170
- }
171
-
172
- body.dark {
173
- background-color: var(--dark-bg);
174
- color: var(--dark-font);
175
- }
176
-
177
- body.dark > .body-wrapper > .footer {
178
- color: var(--dark-font);
179
- }
180
-
181
- body.dark > .body-wrapper > .mc > .module {
182
- background-color: var(--dark-primary);
183
- color: var(--dark-font);
184
- -webkit-box-shadow: -1px 0px 5px 0px var(--dark-shadow);
185
- -moz-box-shadow: -1px 0px 5px 0px var(--dark-shadow);
186
- box-shadow: -1px 0px 5px 0px var(--dark-shadow);
187
- }
188
-
189
- body.dark > .body-wrapper > .mc > .module > .total {
190
- color: var(--dark-blue);
191
- }
192
-
193
- body.dark > .body-wrapper > .mc > .module > .pass {
194
- color: var(--dark-green);
195
- }
196
-
197
- body.dark > .body-wrapper > .mc > .module > .fail {
198
- color: var(--dark-red);
199
- }
200
-
201
- body.dark > .body-wrapper > .configuration-container > .configuration-wrapper > .pass-total {
202
- color: var(--dark-green);
203
- }
204
-
205
- body.dark > .body-wrapper > .configuration-container > .configuration-wrapper > .fail-total {
206
- color: var(--dark-red);
207
- }
208
-
209
- body.dark > .body-wrapper > .mc > .module.danger {
210
- background-color: rgba(255, 0, 0, 0.185);
211
- }
212
-
213
- body.dark > .body-wrapper > .banner-in-the-middle > h1 {
214
- color: var(--dark-font);
215
- }
216
-
217
- body.dark > .body-wrapper > .header {
218
- color: var(--dark-primary);
219
- }
220
-
221
- body.dark > .body-wrapper > .configuration-container > .configuration-wrapper {
222
- color: var(--dark-font);
223
- }
224
-
225
- body.dark > .body-wrapper > .configuration-container > #filter {
226
- background-color: var(--dark-secondary);
227
- -webkit-box-shadow: -1px 0px 5px 0px var(--dark-shadow);
228
- -moz-box-shadow: -1px 0px 5px 0px var(--dark-shadow);
229
- box-shadow: -1px 0px 5px 0px var(--dark-shadow);
230
- }
231
-
232
- body.dark > .body-wrapper > .footer > p > span > a {
233
- color: var(--dark-font);
234
- }
235
-
236
- body.dark > .body-wrapper > .header > div > button > #theme-switch-icon {
237
- color: var(--dark-primary);
238
- }
239
-
240
- body {
241
- background-color: var(--light-bg);
242
- color: var(--dark-font);
243
- }
244
-
245
- body > .body-wrapper > .footer {
246
- color: var(--light-font);
247
- }
248
-
249
- body > .body-wrapper > .mc > .module {
250
- background-color: var(--light-primary);
251
- color: var(--light-font);
252
- }
253
-
254
- body > .body-wrapper > .mc > .module > .total {
255
- color: var(--light-blue);
256
- }
257
-
258
- body > .body-wrapper > .mc > .module > .pass {
259
- color: var(--light-green);
260
- }
261
-
262
- body > .body-wrapper > .mc > .module > .fail {
263
- color: var(--light-red);
264
- }
265
-
266
- body > .body-wrapper > .configuration-container > .configuration-wrapper > .pass-total {
267
- color: var(--light-green);
268
- }
269
-
270
- body > .body-wrapper > .configuration-container > .configuration-wrapper > .fail-total {
271
- color: var(--light-red);
272
- }
273
-
274
- body > .body-wrapper > .mc > .module.danger {
275
- background-color: var(--danger-bg);
276
- }
277
-
278
- body > .body-wrapper > .header {
279
- color: var(--light-primary);
280
- }
281
-
282
- body > .body-wrapper > .configuration-container > .configuration-wrapper {
283
- color: var(--light-font);
284
- }
285
-
286
- body > .body-wrapper > .footer > p > span > a {
287
- color: var(--light-font);
288
- }
289
-
290
- body > .body-wrapper > .header > div > button > #theme-switch-icon {
291
- color: var(--light-primary);
292
- }
293
-
294
- @media only screen and (max-width: 600px) {
295
- h1 {
296
- font-size: 24px;
297
- }
298
-
299
- .mc {
300
- grid-template-columns: 1fr;
301
- padding: 0.5em 0.5em;
302
- padding-top: 1em;
303
- }
304
-
305
- .configuration-container {
306
- padding: 0.5em 0em;
307
- }
308
-
309
- .configuration-wrapper {
310
- padding: 0.5em 1em;
311
- }
312
-
313
- .configuration-icon {
314
- font-size: 1em;
315
- }
316
-
317
- #configuration-text {
318
- font-size: 0.6em;
319
- }
320
-
321
- #filter {
322
- width: 4em;
323
- padding: 0.4em 0.4em;
324
- margin: 0.3em 0.7em 0.3em 0.7em;
325
- }
326
- }
327
-
328
- @media (min-width: 600px) and (max-width: 992px) {
329
- .mc {
330
- grid-template-columns: 1fr 1fr;
331
- }
332
- }
333
- </style>"
334
- end
335
- end