10203040506070809010011012013014015016017018019020021022023024025026027028029030031032033234035236237238039040041042043044045046047048049050135514352053054055056435705879559222600610620630642226506667567368069070071072373074975076077078079080813813820830840850860870882890902912920932940952960972980990100010121021103010401052106431070108010901100111211201132114211501160117011801190120012101220123012401250126112711280129113011310132113311341135113601371138113901401141014221430 /++ 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); }
/++ 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); }