1 /** 2 Copyright: Copyright (c) 2019, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 */ 10 module dextool.plugin.mutate.backend.report.html.page_test_case_unique; 11 12 import logger = std.experimental.logger; 13 import std.format : format; 14 import std.datetime : Clock, dur; 15 16 import arsd.dom : Element, RawSource; 17 18 import dextool.plugin.mutate.backend.database : Database; 19 import dextool.plugin.mutate.backend.report.analyzers : TestCaseUniqueness, 20 reportTestCaseUniqueness; 21 import dextool.plugin.mutate.backend.report.html.constants : htmlFileDir; 22 import dextool.plugin.mutate.backend.report.html.js : js_similarity; 23 import dextool.plugin.mutate.backend.report.html.tmpl : tmplBasicPage, tmplDefaultTable; 24 import dextool.plugin.mutate.backend.type : Mutation; 25 import dextool.plugin.mutate.config : ConfigReport; 26 import dextool.plugin.mutate.type : MutationKind; 27 28 auto makeTestCaseUnique(ref Database db, ref const ConfigReport conf, 29 const(MutationKind)[] humanReadableKinds, const(Mutation.Kind)[] kinds) @trusted { 30 auto doc = tmplBasicPage; 31 32 auto s = doc.root.childElements("head")[0].addChild("script"); 33 s.addChild(new RawSource(doc, js_similarity)); 34 35 doc.title(format("Test Case Uniqueness %(%s %) %s", humanReadableKinds, Clock.currTime)); 36 doc.mainBody.setAttribute("onload", "init()"); 37 doc.mainBody.addChild("p", "This report contains the test cases that uniquely kill mutants, which those mutants are and test cases that aren't unique."); 38 39 toHtml(db, reportTestCaseUniqueness(db, kinds), doc.mainBody); 40 41 return doc.toPrettyString; 42 } 43 44 private: 45 46 void toHtml(ref Database db, TestCaseUniqueness result, Element root) { 47 import std.algorithm : sort, map; 48 import std.array : array; 49 import std.conv : to; 50 import std.path : buildPath; 51 import dextool.cachetools; 52 import dextool.plugin.mutate.backend.database : spinSql, MutationId; 53 import dextool.plugin.mutate.backend.report.html.page_files : pathToHtmlLink; 54 import dextool.type : Path; 55 56 auto getPath = nullableCache!(MutationId, string, (MutationId id) { 57 auto path = spinSql!(() => db.getPath(id)).get; 58 return format!"%s#%s"(buildPath(htmlFileDir, pathToHtmlLink(path)), id); 59 })(0, 30.dur!"seconds"); 60 61 with (root.addChild("button", "expand all")) { 62 setAttribute("type", "button"); 63 setAttribute("id", "expand_all"); 64 } 65 with (root.addChild("button", "collapse all")) { 66 setAttribute("type", "button"); 67 setAttribute("id", "collapse_all"); 68 } 69 70 foreach (const k; result.uniqueKills.byKey.array.sort) { 71 // Containers allows for hiding a table by clicking the corresponding header. 72 // Defaults to hiding tables. 73 auto comp_container = root.addChild("div").addClass("comp_container"); 74 auto heading = comp_container.addChild("h2").addClass("tbl_header"); 75 heading.addChild("i").addClass("right"); 76 heading.appendText(" "); 77 heading.appendText(k.name); 78 auto tbl_container = comp_container.addChild("div").addClass("tbl_container"); 79 tbl_container.setAttribute("style", "display: none;"); 80 auto tbl = tmplDefaultTable(tbl_container, ["Mutation ID"]); 81 82 auto r = tbl.appendRow(); 83 auto mut_ids = r.addChild("td"); 84 foreach (const m; result.uniqueKills[k].sort) { 85 auto link = mut_ids.addChild("a", m.to!string); 86 link.href = getPath(m).get; 87 mut_ids.appendText(" "); 88 } 89 } 90 91 { 92 root.addChild("p", "These are test cases that have no unique kills"); 93 auto tbl = tmplDefaultTable(root, ["Test Case"]); 94 foreach (const tc; result.noUniqueKills.sort) { 95 auto r = tbl.appendRow; 96 r.addChild("td", tc.name); 97 } 98 } 99 }