1 /**
2 Copyright: Copyright (c) 2018, 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_groups;
11 
12 import logger = std.experimental.logger;
13 import std.format : format;
14 
15 import arsd.dom : Document, Element, require, Table;
16 
17 import dextool.plugin.mutate.backend.database : Database;
18 import dextool.plugin.mutate.backend.diff_parser : Diff;
19 import dextool.plugin.mutate.backend.report.analyzers : TestGroupStat, reportTestGroups;
20 import dextool.plugin.mutate.backend.report.html.constants;
21 import dextool.plugin.mutate.backend.report.html.tmpl : tmplBasicPage,
22     tmplDefaultTable, dashboardCss;
23 import dextool.plugin.mutate.backend.type : Mutation;
24 import dextool.plugin.mutate.config : ConfigReport;
25 import dextool.plugin.mutate.type : MutationKind;
26 import dextool.type : AbsolutePath;
27 
28 auto makeTestGroups(ref Database db, ref const ConfigReport conf,
29         const(MutationKind)[] humanReadableKinds, const(Mutation.Kind)[] kinds) @trusted {
30     import std.datetime : Clock;
31 
32     auto doc = tmplBasicPage.dashboardCss;
33     doc.title(format("Test Groups %(%s %) %s", humanReadableKinds, Clock.currTime));
34 
35     if (conf.testGroups.length != 0)
36         doc.mainBody.addChild("h2", "Test Groups");
37     foreach (tg; conf.testGroups)
38         testGroups(reportTestGroups(db, kinds, tg), doc.mainBody);
39 
40     return doc.toPrettyString;
41 }
42 
43 private:
44 
45 void testGroups(const TestGroupStat test_g, Element root) {
46     import std.algorithm : sort, map;
47     import std.array : array;
48     import std.conv : to;
49     import std.path : buildPath;
50     import std.typecons : tuple;
51     import dextool.plugin.mutate.backend.mutation_type : toUser;
52     import dextool.plugin.mutate.backend.report.html.utility : pathToHtmlLink;
53 
54     root.addChild("h3", test_g.description);
55 
56     auto stat_tbl = tmplDefaultTable(root, ["Property", "Value"]);
57     foreach (const d; [
58             tuple("Mutation Score", test_g.stats.score.to!string),
59             tuple("Alive", test_g.stats.alive.to!string),
60             tuple("Total", test_g.stats.total.to!string)
61         ]) {
62         auto r = stat_tbl.appendRow();
63         r.addChild("td", d[0]);
64         r.addChild("td", d[1]);
65     }
66 
67     with (root.addChild("p")) {
68         appendText("Mutation data per file.");
69         appendText("The killed mutants are those that where killed by this test group.");
70         appendText("Therefor the total here is less than the reported total.");
71     }
72 
73     auto file_tbl = tmplDefaultTable(root, ["File", "Alive", "Killed"]);
74 
75     foreach (const pkv; test_g.files
76             .byKeyValue
77             .map!(a => tuple(a.key, a.value.dup))
78             .array
79             .sort!((a, b) => a[1] < b[1])) {
80         auto r = file_tbl.appendRow();
81 
82         const path = test_g.files[pkv[0]];
83         r.addChild("td", path);
84 
85         auto alive_ids = r.addChild("td").setAttribute("valign", "top");
86         if (auto alive = pkv[0] in test_g.alive) {
87             foreach (a; (*alive).dup.sort!((a, b) => a.sloc.line < b.sloc.line)) {
88                 auto link = alive_ids.addChild("a", format("%s:%s", a.kind.toUser, a.sloc.line));
89                 link.href = format("%s#%s", buildPath(Html.fileDir, pathToHtmlLink(path)), a.id);
90                 alive_ids.appendText(" ");
91             }
92         }
93 
94         auto killed_ids = r.addChild("td").setAttribute("valign", "top");
95         if (auto killed = pkv[0] in test_g.killed) {
96             foreach (a; (*killed).dup.sort!((a, b) => a.sloc.line < b.sloc.line)) {
97                 auto link = killed_ids.addChild("a", format("%s:%s", a.kind.toUser, a.sloc.line));
98                 link.href = format("%s#%s", buildPath(Html.fileDir, pathToHtmlLink(path)), a.id);
99                 killed_ids.appendText(" ");
100             }
101         }
102     }
103 
104     auto tc_tbl = tmplDefaultTable(root, ["Test Case"]);
105     foreach (tc; test_g.testCases) {
106         tc_tbl.appendRow(tc.name);
107     }
108 }