trial.reporters.html 41/43(95%) line coverage

      
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
170
180
190
200
210
220
230
240
250
260
270
280
290
300
310
320
332
340
352
362
372
380
390
400
410
420
430
440
450
460
470
480
490
50135
5143
520
530
540
550
5643
570
58795
59222
600
610
620
630
64222
650
66675
673
680
690
700
710
723
730
749
750
760
770
780
790
80813
813
820
830
840
850
860
870
882
890
902
912
920
932
940
952
960
972
980
990
1000
1012
1021
1030
1040
1052
10643
1070
1080
1090
1100
1112
1120
1132
1142
1150
1160
1170
1180
1190
1200
1210
1220
1230
1240
1250
1261
1271
1280
1291
1301
1310
1321
1331
1341
1351
1360
1371
1381
1390
1401
1410
1422
1430
/++ A module containing the HtmlReporter Copyright: © 2017 Szabo Bogdan License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. Authors: Szabo Bogdan +/ module trial.reporters.html; import std.stdio; import std.array; import std.conv; import std.datetime; import std.string; import std.algorithm; import std.file; import std.path; import trial.interfaces; import trial.reporters.writer; /// The "html" reporter outputs a hierarchical HTML body representation of your tests. class HtmlReporter : ILifecycleListener { private { bool success = true; immutable string destination; immutable long warningTestDuration; immutable long dangerTestDuration; } this(string destination, long warningTestDuration, long dangerTestDuration) { this.destination = destination; this.warningTestDuration = warningTestDuration; this.dangerTestDuration = dangerTestDuration; } void begin(ulong) { } void update() { } private { void relativePaths(ref SuiteResult[] results) { foreach(ref result; results) { relativePaths(result); } } void relativePaths(ref SuiteResult suite) { relativePaths(suite.attachments); foreach(ref result; suite.tests) { relativePaths(result); } } void relativePaths(ref TestResult step) { relativePaths(step.attachments); foreach(ref child; step.steps) { relativePaths(child); } } void relativePaths(ref StepResult step) { relativePaths(step.attachments); foreach(ref child; step.steps) { relativePaths(child); } } void relativePaths(ref Attachment[] attachments) { foreach(ref attachment; attachments) { attachment.file = asRelativePath(attachment.file, destination.dirName).array; } } } void end(SuiteResult[] results) { relativePaths(results); immutable string trialCss = import("assets/trial.css"); immutable string trialJs = import("assets/trial.js"); string content = import("templates/htmlReporter.html"); auto assets = buildPath(destination.dirName, "assets"); if(!destination.dirName.exists) { mkdirRecurse(destination.dirName); } if(!assets.exists) { mkdirRecurse(assets); } content = content .replace("{testResult}", "[" ~ results.map!(a => a.toString).join(",") ~ "]") .replace("{warningTestDuration}", warningTestDuration.to!string) .replace("{dangerTestDuration}", dangerTestDuration.to!string); std.file.write(destination, content); std.file.write(buildPath(assets, "trial.css"), trialCss); std.file.write(buildPath(assets, "trial.js"), trialJs); } } version (unittest) { import fluent.asserts; } @("it should set the result json") unittest { auto writer = new BufferedWriter; auto reporter = new HtmlReporter("trial-result.html", 0, 0); auto begin = Clock.currTime - 10.seconds; auto end = begin + 10.seconds; auto testResult = new TestResult("some test"); testResult.begin = begin; testResult.end = end; testResult.status = TestResult.Status.success; SuiteResult[] result = [SuiteResult("Test Suite", begin, end, [testResult])]; reporter.end(result); auto text = readText("trial-result.html"); text.should.contain(result[0].toString); }