1 /++ 2 A module containing the LandingReporter 3 4 This is an example of how this reporter looks 5 <script type="text/javascript" src="https://asciinema.org/a/ar2qel0uzunpjmfzkg7xtvsa1.js" id="asciicast-ar2qel0uzunpjmfzkg7xtvsa1" async></script> 6 7 Copyright: © 2017 Szabo Bogdan 8 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 9 Authors: Szabo Bogdan 10 +/ 11 module trial.reporters.landing; 12 13 import std.stdio; 14 import std.array; 15 import std.conv; 16 import std.datetime; 17 import std..string; 18 import std.algorithm; 19 20 import trial.interfaces; 21 import trial.reporters.writer; 22 23 /// 24 struct LandingGlyphs { 25 string plane = "✈"; 26 string margin = "━"; 27 string lane = "⋅"; 28 } 29 30 /// 31 string landingGlyphsToCode(LandingGlyphs glyphs) { 32 return "LandingGlyphs(`"~ glyphs.plane ~"`,`"~ glyphs.margin ~"`,`"~ glyphs.lane ~"`)"; 33 } 34 35 /// The Landing Strip (landing) reporter is a gimmicky test reporter simulating a plane landing unicode ftw 36 class LandingReporter : ITestCaseLifecycleListener, ILifecycleListener 37 { 38 private 39 { 40 ReportWriter writer; 41 LandingGlyphs glyphs; 42 43 ulong testCount; 44 ulong currentTest; 45 bool success = true; 46 } 47 48 this(LandingGlyphs glyphs) 49 { 50 writer = defaultWriter; 51 this.glyphs = glyphs; 52 } 53 54 this(ReportWriter writer) 55 { 56 this.writer = writer; 57 } 58 59 void begin(ulong testCount) 60 { 61 this.testCount = testCount; 62 writer.writeln("\n\n"); 63 drawLane; 64 } 65 66 void update() 67 { 68 69 } 70 71 void end(SuiteResult[]) 72 { 73 74 } 75 76 void begin(string suite, ref TestResult test) 77 { 78 } 79 80 void end(string suite, ref TestResult test) 81 { 82 currentTest++; 83 success = success && test.status == TestResult.Status.success; 84 drawLane; 85 } 86 87 private void drawLane() 88 { 89 size_t size = (writer.width / 4) * 3; 90 size_t position = ((cast(double) currentTest / cast(double) testCount) * size).to!size_t; 91 92 writer.goTo(3); 93 writer.writeln(glyphs.margin.replicate(size), ReportWriter.Context.inactive); 94 95 if (currentTest < testCount) 96 { 97 writer.write(glyphs.lane.replicate(position), ReportWriter.Context.inactive); 98 writer.write(glyphs.plane, success ? ReportWriter.Context.active : ReportWriter.Context.danger); 99 writer.writeln(glyphs.lane.replicate(size - position - 1), ReportWriter.Context.inactive); 100 } 101 else 102 { 103 writer.write(glyphs.lane.replicate(size), ReportWriter.Context.inactive); 104 writer.writeln(glyphs.plane, success ? ReportWriter.Context.active : ReportWriter.Context.danger); 105 } 106 107 writer.writeln(glyphs.margin.replicate(size), ReportWriter.Context.inactive); 108 } 109 } 110 111 version (unittest) 112 { 113 version(Have_fluent_asserts) { 114 import fluent.asserts; 115 } 116 } 117 118 @("it should print 10 success tests") 119 unittest 120 { 121 auto writer = new BufferedWriter; 122 auto reporter = new LandingReporter(writer); 123 124 auto suite = SuiteResult("some suite"); 125 auto test = new TestResult("some test"); 126 test.status = TestResult.Status.success; 127 reporter.begin(10); 128 129 writer.buffer.should.equal("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" ~ "✈⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅⋅\n" ~ "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); 130 131 auto position = [18, 36, 54, 72, 90, 108, 126, 144, 162, 180]; 132 133 foreach (i; 0 .. 10) 134 { 135 reporter.begin("some suite", test); 136 reporter.end("some suite", test); 137 138 auto lines = writer.buffer.split("\n"); 139 lines.length.should.equal(4); 140 lines[1].indexOf("✈").should.equal(position[i]); 141 } 142 }