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 }