File size: 10,024 Bytes
7a3b3da
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<!doctype html>
<html><head><meta charset="utf-8"><title>pending</title></head>
<body>
<div id="host"></div>
<script>
/* Loads ../index.html into this document, then drives the widgets with real click
   events and asserts the readouts. Results are written into document.title so
   `chrome --headless --dump-dom` can report them. */
var results = [];
function check(name, got, want) {
  results.push((String(got) === String(want) ? "PASS" : "FAIL") + " " + name +
               " got=" + got + " want=" + want);
}

fetch("../index.html").then(function (r) { return r.text(); }).then(function (html) {
  var doc = new DOMParser().parseFromString(html, "text/html");

  // move body content in, then re-execute scripts (innerHTML does not run them)
  document.getElementById("host").innerHTML = doc.body.innerHTML;
  var scripts = Array.prototype.slice.call(document.querySelectorAll("#host script"));
  var chain = Promise.resolve();
  scripts.forEach(function (old) {
    chain = chain.then(function () {
      return new Promise(function (done) {
        var s = document.createElement("script");
        // getAttribute keeps the raw relative path; .src would already be resolved
        // against this page's directory, which is one level too deep.
        var raw = old.getAttribute("src");
        if (raw) { s.src = "../" + raw; s.onload = done; s.onerror = done; }
        else { s.textContent = old.textContent; }
        document.head.appendChild(s);
        if (!raw) { done(); }
      });
    });
  });

  return chain.then(function () { return new Promise(function (r2) { setTimeout(r2, 120); }); });
}).then(function () {
  var chips = document.querySelectorAll("#tw-chips .chip");
  var unionVal = function () {
    return document.querySelectorAll("#tw-grid .tcell.on").length;
  };
  var readout = function () { return document.getElementById("tw-readout").textContent; };

  check("widgets built: chips", chips.length, 4);
  check("grid cells", document.querySelectorAll("#tw-grid .tcell").length, 41);
  check("all-4 union highlighted", unionVal(), 29);
  check("readout shows 29", /29\/41/.test(readout()), true);
  check("readout shows merge 28", /28\/41/.test(readout()), true);

  // turn OFF Spec. A -> union(B,C,D) should still be 29
  chips[0].click();
  check("A off -> union(BCD)", unionVal(), 29);

  // turn OFF B and C -> D alone = 27
  chips[1].click(); chips[2].click();
  check("D alone", unionVal(), 27);

  // D off too -> nothing selected
  chips[3].click();
  check("none selected", unionVal(), 0);

  // back to A + D only  -> 29 (complementary pair)
  chips[0].click(); chips[3].click();
  check("A+D complementary pair", unionVal(), 29);

  // full set again, then compare-with-merge ring counts
  chips[1].click(); chips[2].click();
  check("back to all four", unionVal(), 29);
  document.getElementById("tw-cmp").click();
  check("merge-only ring (gain)", document.querySelectorAll("#tw-grid .tcell.gain").length, 1);
  check("union-only ring (loss)", document.querySelectorAll("#tw-grid .tcell.loss").length, 2);

  // cluster widget
  var bars = document.querySelectorAll("#cl-bars .cbar");
  check("cluster rows", bars.length, 7);
  var firstDelta = bars[0].querySelector(".cd").textContent.trim();
  check("default sort = biggest gain first", firstDelta, "+14.8");
  var sortChips = document.querySelectorAll("#cl-chips .chip");
  sortChips[1].click(); // by base rate ascending
  var b2 = document.querySelectorAll("#cl-bars .cbar");
  check("sort by base rate -> lowest base first",
        /ML & scientific/.test(b2[0].querySelector(".cname").textContent), true);
  sortChips[2].click(); // by cluster size
  var b3 = document.querySelectorAll("#cl-bars .cbar");
  check("sort by size -> n=23 first",
        /n=23/.test(b3[0].querySelector(".cname").textContent), true);
  document.getElementById("cl-base").click(); // hide base
  check("hide base removes grey fills", document.querySelectorAll("#cl-bars .fill.b").length, 0);

  // curve widget
  check("curve dots", document.querySelectorAll("#cv-chart .dot").length, 37);
  check("best-so-far polyline", document.querySelectorAll("#cv-chart .best").length, 1);
  document.getElementById("cv-all").click();
  check("hide variants", document.querySelectorAll("#cv-chart .dot").length, 0);
  document.getElementById("cv-best").click();
  check("hide envelope", document.querySelectorAll("#cv-chart .best").length, 0);

  // sortable table: WAI overall row must stay pinned last
  var wai = document.querySelectorAll("table.sortable")[2];
  var ths = wai.querySelectorAll("thead th");
  ths[6].click(); // sort by Monet (DarwinX)
  var rows = wai.querySelectorAll("tbody tr");
  check("total row stays last after sort",
        rows[rows.length - 1].classList.contains("total"), true);
  var firstCell = rows[0].cells[6].textContent.trim();
  check("descending sort puts 98.3 first", firstCell, "98.3");
  ths[6].click(); // ascending
  var rows2 = wai.querySelectorAll("tbody tr");
  check("ascending sort puts 84.0 first", rows2[0].cells[6].textContent.trim(), "84.0");
  check("total still last", rows2[rows2.length - 1].classList.contains("total"), true);

  // ---- headline panels ----
  check("headline panels", document.querySelectorAll("#hl-panels .panel").length, 4);
  check("prior bars present", document.querySelectorAll("#hl-panels .bar.p").length, 3);
  var wa = document.querySelectorAll("#hl-panels .panel")[2];
  var hOwn = parseFloat(wa.querySelector(".bar.e").getAttribute("height"));
  document.querySelectorAll("#hl-chips .chip")[1].click(); // shared 0-100
  var wa2 = document.querySelectorAll("#hl-panels .panel")[2];
  var hShared = parseFloat(wa2.querySelector(".bar.e").getAttribute("height"));
  check("shared axis changes bar geometry", hShared !== hOwn, true);
  var tb = document.querySelectorAll("#hl-panels .panel")[0];
  var tbH = parseFloat(tb.querySelector(".bar.e").getAttribute("height"));
  check("shared axis: TB2.1 bar shorter than WAI bar", tbH < hShared, true);
  document.getElementById("hl-prior").click();
  check("hide prior removes its bars", document.querySelectorAll("#hl-panels .bar.p").length, 0);
  document.querySelectorAll("#hl-chips .chip")[0].click(); // back to per-panel

  // ---- TerminalWorld specialist bars ----
  var spRows = document.querySelectorAll("#sp-rows .hrow");
  check("specialist rows (6 bars + ref tag)", spRows.length, 7);
  check("percent shown by default", /68\.3%/.test(document.getElementById("sp-rows").textContent), true);
  var spW = function (n) {
    return parseFloat(document.querySelectorAll("#sp-rows .hf")[n].style.width);
  };
  var zoomSpread = spW(5) - spW(1);   // merged minus weakest specialist
  document.querySelectorAll("#sp-chips .chip")[1].click();   // full 0-100 axis
  var fullSpread = spW(5) - spW(1);
  check("zoomed axis magnifies the spread", zoomSpread > fullSpread * 3, true);
  check("full axis puts merged at its true 68.3%", Math.round(spW(5) * 10) / 10, 68.3);
  document.querySelectorAll("#sp-chips .chip")[0].click();
  document.getElementById("sp-counts").click();
  check("counts toggle shows 28/41", /28\/41/.test(document.getElementById("sp-rows").textContent), true);

  // ---- TB2.1 compute ----
  check("compute rows (2 groups x 2 series)", document.querySelectorAll("#cp-rows .hrow").length, 4);
  var cpVals = function () {
    return Array.prototype.map.call(document.querySelectorAll("#cp-rows .hv"),
      function (e) { return e.textContent.trim(); }).join(",");
  };
  check("turns shown first", cpVals(), "11,22,12,13");
  document.querySelectorAll("#cp-chips .chip")[1].click();
  check("tokens toggle shows K values", cpVals(), "89K,380K,125K,172K");

  // ---- WAI invalid composition ----
  check("two stacked rows", document.querySelectorAll("#iv-rows .stack").length, 2);
  var mechSegs = document.querySelectorAll("#iv-rows .stack i").length;
  check("mechanism view: 4 before + 1 after segments", mechSegs, 5);
  check("totals rendered 293 and 17",
        /293/.test(document.getElementById("iv-rows").textContent) &&
        /17/.test(document.getElementById("iv-rows").textContent), true);
  var afterStack = document.querySelectorAll("#iv-rows .stack")[1];
  var wShared = afterStack.querySelector("i").style.width;
  document.getElementById("iv-norm").click();
  var wNorm = document.querySelectorAll("#iv-rows .stack")[1].querySelector("i").style.width;
  check("normalising widens the after row", parseFloat(wNorm) > parseFloat(wShared), true);
  check("after row fills the width when normalised", parseFloat(wNorm), 100);
  document.querySelectorAll("#iv-chips .chip")[0].click(); // by application
  check("application view segment count",
        document.querySelectorAll("#iv-rows .stack i").length, 9 + 5);

  // ---- WAI audit dumbbell ----
  check("audit lanes (11 apps x 2)", document.querySelectorAll("#ad-rows .seg").length, 22);
  check("axis row precedes the data rows",
        /pass@1/.test(document.querySelectorAll("#ad-rows .drow")[0].textContent), true);
  check("overall row pinned first",
        document.querySelectorAll("#ad-rows .drow")[1].textContent.indexOf("Overall"), 0);
  document.getElementById("ad-base").click();
  check("hiding base halves the lanes", document.querySelectorAll("#ad-rows .seg").length, 11);
  document.getElementById("ad-base").click();
  document.getElementById("ad-sort").click();
  var firstAfterOverall = document.querySelectorAll("#ad-rows .drow")[2].querySelector(".dn").textContent;
  // Superhuman loses the most to the audit: 53.3 -> 31.7 = 21.6, ahead of Gmail's 20.0.
  check("sort by audit loss puts Superhuman first", firstAfterOverall, "Superhuman");

  var fails = results.filter(function (r) { return r.indexOf("FAIL") === 0; });
  document.title = "RESULT " + (fails.length ? "FAILURES=" + fails.length : "ALL PASS") +
                   " || " + results.join(" || ");
}).catch(function (e) {
  document.title = "RESULT ERROR " + e.message + " || " + results.join(" || ");
});
</script>
</body></html>