| 1 | TracWysiwyg.TestUnit = function() { |
|---|
| 2 | this.cases = {}; |
|---|
| 3 | this.assertCounts = {}; |
|---|
| 4 | this.current = null; |
|---|
| 5 | }; |
|---|
| 6 | |
|---|
| 7 | (function() { |
|---|
| 8 | var prototype = TracWysiwyg.TestUnit.prototype; |
|---|
| 9 | |
|---|
| 10 | prototype.inspect = function(value) { |
|---|
| 11 | var type = typeof value; |
|---|
| 12 | switch (type) { |
|---|
| 13 | case "string": |
|---|
| 14 | return value.replace(/[\u0000-\u001f\\\u007f\ufffe\uffff]/g, function(m) { |
|---|
| 15 | var code = m.charCodeAt(0); |
|---|
| 16 | switch (code) { |
|---|
| 17 | case 9: return "\\t"; |
|---|
| 18 | case 10: return "\\n"; |
|---|
| 19 | case 11: return "\\v"; |
|---|
| 20 | case 12: return "\\f"; |
|---|
| 21 | case 13: return "\\r"; |
|---|
| 22 | case 92: return "\\\\"; |
|---|
| 23 | } |
|---|
| 24 | return "\\u" + (0x10000 + code).toString(16).substring(1); |
|---|
| 25 | }); |
|---|
| 26 | break; |
|---|
| 27 | case "object": |
|---|
| 28 | case "function": |
|---|
| 29 | if (value instanceof RegExp) { |
|---|
| 30 | return value.toString(); |
|---|
| 31 | } |
|---|
| 32 | } |
|---|
| 33 | return "{%}".replace("%", type) + value.toString(); |
|---|
| 34 | }; |
|---|
| 35 | |
|---|
| 36 | prototype.fragment = function() { |
|---|
| 37 | var start = 0; |
|---|
| 38 | var arg = arguments[0]; |
|---|
| 39 | var d; |
|---|
| 40 | if (arg.nodeType != 9) { |
|---|
| 41 | d = document; |
|---|
| 42 | } |
|---|
| 43 | else { |
|---|
| 44 | d = arg; |
|---|
| 45 | start = 1; |
|---|
| 46 | } |
|---|
| 47 | var fragment = d.createDocumentFragment(); |
|---|
| 48 | var length = arguments.length; |
|---|
| 49 | for (var i = start; i < length; i++) { |
|---|
| 50 | fragment.appendChild(arguments[i]); |
|---|
| 51 | } |
|---|
| 52 | return fragment; |
|---|
| 53 | }; |
|---|
| 54 | |
|---|
| 55 | prototype.element = function(tag) { |
|---|
| 56 | var start = 0; |
|---|
| 57 | var arg = arguments[start++]; |
|---|
| 58 | var d, tag; |
|---|
| 59 | if (typeof arg == "string") { |
|---|
| 60 | d = document; |
|---|
| 61 | tag = arg; |
|---|
| 62 | } |
|---|
| 63 | else { |
|---|
| 64 | d = arg; |
|---|
| 65 | tag = arguments[start++]; |
|---|
| 66 | } |
|---|
| 67 | var element = d.createElement(tag); |
|---|
| 68 | for (var i = start; i < arguments.length; i++) { |
|---|
| 69 | arg = arguments[i]; |
|---|
| 70 | switch (typeof arg) { |
|---|
| 71 | case "object": |
|---|
| 72 | if (typeof arg.nodeType == "undefined") { |
|---|
| 73 | for (var name in arg) { |
|---|
| 74 | var value = arg[name]; |
|---|
| 75 | switch (name) { |
|---|
| 76 | case "id": |
|---|
| 77 | element.id = value; |
|---|
| 78 | break; |
|---|
| 79 | case "class": case "className": |
|---|
| 80 | element.className = value; |
|---|
| 81 | break; |
|---|
| 82 | default: |
|---|
| 83 | element.setAttribute(name, value); |
|---|
| 84 | break; |
|---|
| 85 | } |
|---|
| 86 | } |
|---|
| 87 | continue; |
|---|
| 88 | } |
|---|
| 89 | break; |
|---|
| 90 | case "string": |
|---|
| 91 | arg = d.createTextNode(arg); |
|---|
| 92 | break; |
|---|
| 93 | } |
|---|
| 94 | element.appendChild(arg); |
|---|
| 95 | } |
|---|
| 96 | return element; |
|---|
| 97 | }; |
|---|
| 98 | |
|---|
| 99 | prototype.text = function() { |
|---|
| 100 | var start = 0; |
|---|
| 101 | var arg = arguments[start++]; |
|---|
| 102 | var d, text; |
|---|
| 103 | if (typeof arg == "string") { |
|---|
| 104 | d = document; |
|---|
| 105 | text = arg; |
|---|
| 106 | } |
|---|
| 107 | else { |
|---|
| 108 | d = arg; |
|---|
| 109 | text = arguments[start++]; |
|---|
| 110 | } |
|---|
| 111 | return d.createTextNode(text); |
|---|
| 112 | }; |
|---|
| 113 | |
|---|
| 114 | prototype.$ = function(id) { |
|---|
| 115 | return typeof id == "string" ? document.getElementById(id) : id; |
|---|
| 116 | }; |
|---|
| 117 | |
|---|
| 118 | prototype.add = function(name, method) { |
|---|
| 119 | if (name in this.cases) { |
|---|
| 120 | throw "'" + name + "' is in use."; |
|---|
| 121 | } |
|---|
| 122 | this.cases[name] = method; |
|---|
| 123 | this.assertCounts[name] = 0; |
|---|
| 124 | }; |
|---|
| 125 | |
|---|
| 126 | prototype.assertEqual = function(expected, actual, label) { |
|---|
| 127 | var count = ++this.assertCounts[this.current]; |
|---|
| 128 | if (typeof (expected) == typeof (actual) && expected == actual) { |
|---|
| 129 | return true; |
|---|
| 130 | } |
|---|
| 131 | throw (label || "") + "[" + count + "]\n" |
|---|
| 132 | + this.inspect(expected) + " (" + expected.length + ")\n" |
|---|
| 133 | + this.inspect(actual) + " (" + actual.length + ")"; |
|---|
| 134 | }; |
|---|
| 135 | |
|---|
| 136 | prototype.assertMatch = function(pattern, string, label) { |
|---|
| 137 | var count = ++this.assertCounts[this.current]; |
|---|
| 138 | if (pattern.test(string)) { |
|---|
| 139 | return true; |
|---|
| 140 | } |
|---|
| 141 | throw (label || "") + "[" + count + "]\n" |
|---|
| 142 | + this.inspect(pattern) + "\n" |
|---|
| 143 | + this.inspect(string) + " (" + string.length + ")"; |
|---|
| 144 | }; |
|---|
| 145 | |
|---|
| 146 | prototype.run = function() { |
|---|
| 147 | var self = this |
|---|
| 148 | var $ = this.$, element = this.element, text = this.text; |
|---|
| 149 | var d = document; |
|---|
| 150 | var cases = this.cases; |
|---|
| 151 | var assertCounts = this.assertCounts; |
|---|
| 152 | var names = []; |
|---|
| 153 | for (var name in cases) { |
|---|
| 154 | names.push(name); |
|---|
| 155 | assertCounts[name] = 0; |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | var container = $("testunit"); |
|---|
| 159 | var count; |
|---|
| 160 | if (container) { |
|---|
| 161 | container.parentNode.removeChild(container); |
|---|
| 162 | } |
|---|
| 163 | container = element( |
|---|
| 164 | "table", { id: "testunit" }, |
|---|
| 165 | element("caption", { id: "testunit.summary" }), |
|---|
| 166 | element("tbody", { id: "testunit.body" })); |
|---|
| 167 | d.body.appendChild(container); |
|---|
| 168 | var body = $("testunit.body"); |
|---|
| 169 | var summary = $("testunit.summary"); |
|---|
| 170 | for (count = 0; count < names.length; count++) { |
|---|
| 171 | body.appendChild( |
|---|
| 172 | element("tr", |
|---|
| 173 | element("td", names[count]), |
|---|
| 174 | element("td", { id: "testcase." + count }, "..."))); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | count = 0; |
|---|
| 178 | var success = 0; |
|---|
| 179 | var invoke = function() { |
|---|
| 180 | if (count >= names.length) { |
|---|
| 181 | self.current = null; |
|---|
| 182 | return; |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | var current = names[count]; |
|---|
| 186 | self.current = current; |
|---|
| 187 | var cell = $("testcase." + count); |
|---|
| 188 | cell.className = "current"; |
|---|
| 189 | try { |
|---|
| 190 | cases[current].call(self); |
|---|
| 191 | cell.className = "success"; |
|---|
| 192 | cell.replaceChild(text("OK"), cell.firstChild); |
|---|
| 193 | success++; |
|---|
| 194 | } |
|---|
| 195 | catch (e) { |
|---|
| 196 | cell.className = "failure"; |
|---|
| 197 | var message = e.message || e.toString(); |
|---|
| 198 | if (e.stack) { |
|---|
| 199 | message = [ message, e.stack ].join("\n\n"); |
|---|
| 200 | } |
|---|
| 201 | cell.replaceChild( |
|---|
| 202 | element("textarea", { id: "testcase." + count + ".textarea", |
|---|
| 203 | rows: message.split("\n").length, |
|---|
| 204 | cols: 80, |
|---|
| 205 | readonly: "readonly" }), |
|---|
| 206 | cell.firstChild); |
|---|
| 207 | $("testcase." + count + ".textarea").value = message; |
|---|
| 208 | } |
|---|
| 209 | summary.innerHTML = success + " / " + names.length; |
|---|
| 210 | |
|---|
| 211 | count++; |
|---|
| 212 | setTimeout(invoke, 10); |
|---|
| 213 | }; |
|---|
| 214 | |
|---|
| 215 | invoke(); |
|---|
| 216 | }; |
|---|
| 217 | })(); |
|---|