|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 // Test cases borrowed and adapted from: |
|
5 // https://github.com/joyent/node/blob/6101eb184db77d0b11eb96e48744e57ecce4b73d/test/simple/test-assert.js |
|
6 // MIT license: http://opensource.org/licenses/MIT |
|
7 |
|
8 function run_test() { |
|
9 let ns = {}; |
|
10 Components.utils.import("resource://testing-common/Assert.jsm", ns); |
|
11 let assert = new ns.Assert(); |
|
12 |
|
13 function makeBlock(f, ...args) { |
|
14 return function() { |
|
15 return f.apply(assert, args); |
|
16 }; |
|
17 } |
|
18 |
|
19 function protoCtrChain(o) { |
|
20 let result = []; |
|
21 while (o = o.__proto__) { |
|
22 result.push(o.constructor); |
|
23 } |
|
24 return result.join(); |
|
25 } |
|
26 |
|
27 function indirectInstanceOf(obj, cls) { |
|
28 if (obj instanceof cls) { |
|
29 return true; |
|
30 } |
|
31 let clsChain = protoCtrChain(cls.prototype); |
|
32 let objChain = protoCtrChain(obj); |
|
33 return objChain.slice(-clsChain.length) === clsChain; |
|
34 }; |
|
35 |
|
36 assert.ok(indirectInstanceOf(ns.Assert.AssertionError.prototype, Error), |
|
37 "Assert.AssertionError instanceof Error"); |
|
38 |
|
39 assert.throws(makeBlock(assert.ok, false), |
|
40 ns.Assert.AssertionError, "ok(false)"); |
|
41 |
|
42 assert.ok(true, "ok(true)"); |
|
43 |
|
44 assert.ok("test", "ok('test')"); |
|
45 |
|
46 assert.throws(makeBlock(assert.equal, true, false), ns.Assert.AssertionError, "equal"); |
|
47 |
|
48 assert.equal(null, null, "equal"); |
|
49 |
|
50 assert.equal(undefined, undefined, "equal"); |
|
51 |
|
52 assert.equal(null, undefined, "equal"); |
|
53 |
|
54 assert.equal(true, true, "equal"); |
|
55 |
|
56 assert.notEqual(true, false, "notEqual"); |
|
57 |
|
58 assert.throws(makeBlock(assert.notEqual, true, true), |
|
59 ns.Assert.AssertionError, "notEqual"); |
|
60 |
|
61 assert.throws(makeBlock(assert.strictEqual, 2, "2"), |
|
62 ns.Assert.AssertionError, "strictEqual"); |
|
63 |
|
64 assert.throws(makeBlock(assert.strictEqual, null, undefined), |
|
65 ns.Assert.AssertionError, "strictEqual"); |
|
66 |
|
67 assert.notStrictEqual(2, "2", "notStrictEqual"); |
|
68 |
|
69 // deepEquals joy! |
|
70 // 7.2 |
|
71 assert.deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14), "deepEqual date"); |
|
72 |
|
73 assert.throws(makeBlock(assert.deepEqual, new Date(), new Date(2000, 3, 14)), |
|
74 ns.Assert.AssertionError, |
|
75 "deepEqual date"); |
|
76 |
|
77 // 7.3 |
|
78 assert.deepEqual(/a/, /a/); |
|
79 assert.deepEqual(/a/g, /a/g); |
|
80 assert.deepEqual(/a/i, /a/i); |
|
81 assert.deepEqual(/a/m, /a/m); |
|
82 assert.deepEqual(/a/igm, /a/igm); |
|
83 assert.throws(makeBlock(assert.deepEqual, /ab/, /a/)); |
|
84 assert.throws(makeBlock(assert.deepEqual, /a/g, /a/)); |
|
85 assert.throws(makeBlock(assert.deepEqual, /a/i, /a/)); |
|
86 assert.throws(makeBlock(assert.deepEqual, /a/m, /a/)); |
|
87 assert.throws(makeBlock(assert.deepEqual, /a/igm, /a/im)); |
|
88 |
|
89 let re1 = /a/; |
|
90 re1.lastIndex = 3; |
|
91 assert.throws(makeBlock(assert.deepEqual, re1, /a/)); |
|
92 |
|
93 // 7.4 |
|
94 assert.deepEqual(4, "4", "deepEqual == check"); |
|
95 assert.deepEqual(true, 1, "deepEqual == check"); |
|
96 assert.throws(makeBlock(assert.deepEqual, 4, "5"), |
|
97 ns.Assert.AssertionError, |
|
98 "deepEqual == check"); |
|
99 |
|
100 // 7.5 |
|
101 // having the same number of owned properties && the same set of keys |
|
102 assert.deepEqual({a: 4}, {a: 4}); |
|
103 assert.deepEqual({a: 4, b: "2"}, {a: 4, b: "2"}); |
|
104 assert.deepEqual([4], ["4"]); |
|
105 assert.throws(makeBlock(assert.deepEqual, {a: 4}, {a: 4, b: true}), |
|
106 ns.Assert.AssertionError); |
|
107 assert.deepEqual(["a"], {0: "a"}); |
|
108 |
|
109 let a1 = [1, 2, 3]; |
|
110 let a2 = [1, 2, 3]; |
|
111 a1.a = "test"; |
|
112 a1.b = true; |
|
113 a2.b = true; |
|
114 a2.a = "test"; |
|
115 assert.throws(makeBlock(assert.deepEqual, Object.keys(a1), Object.keys(a2)), |
|
116 ns.Assert.AssertionError); |
|
117 assert.deepEqual(a1, a2); |
|
118 |
|
119 let nbRoot = { |
|
120 toString: function() { return this.first + " " + this.last; } |
|
121 }; |
|
122 |
|
123 function nameBuilder(first, last) { |
|
124 this.first = first; |
|
125 this.last = last; |
|
126 return this; |
|
127 } |
|
128 nameBuilder.prototype = nbRoot; |
|
129 |
|
130 function nameBuilder2(first, last) { |
|
131 this.first = first; |
|
132 this.last = last; |
|
133 return this; |
|
134 } |
|
135 nameBuilder2.prototype = nbRoot; |
|
136 |
|
137 let nb1 = new nameBuilder("Ryan", "Dahl"); |
|
138 let nb2 = new nameBuilder2("Ryan", "Dahl"); |
|
139 |
|
140 assert.deepEqual(nb1, nb2); |
|
141 |
|
142 nameBuilder2.prototype = Object; |
|
143 nb2 = new nameBuilder2("Ryan", "Dahl"); |
|
144 assert.throws(makeBlock(assert.deepEqual, nb1, nb2), ns.Assert.AssertionError); |
|
145 |
|
146 // String literal + object |
|
147 assert.throws(makeBlock(assert.deepEqual, "a", {}), ns.Assert.AssertionError); |
|
148 |
|
149 // Testing the throwing |
|
150 function thrower(errorConstructor) { |
|
151 throw new errorConstructor("test"); |
|
152 } |
|
153 let aethrow = makeBlock(thrower, ns.Assert.AssertionError); |
|
154 aethrow = makeBlock(thrower, ns.Assert.AssertionError); |
|
155 |
|
156 // the basic calls work |
|
157 assert.throws(makeBlock(thrower, ns.Assert.AssertionError), |
|
158 ns.Assert.AssertionError, "message"); |
|
159 assert.throws(makeBlock(thrower, ns.Assert.AssertionError), ns.Assert.AssertionError); |
|
160 assert.throws(makeBlock(thrower, ns.Assert.AssertionError)); |
|
161 |
|
162 // if not passing an error, catch all. |
|
163 assert.throws(makeBlock(thrower, TypeError)); |
|
164 |
|
165 // when passing a type, only catch errors of the appropriate type |
|
166 let threw = false; |
|
167 try { |
|
168 assert.throws(makeBlock(thrower, TypeError), ns.Assert.AssertionError); |
|
169 } catch (e) { |
|
170 threw = true; |
|
171 assert.ok(e instanceof TypeError, "type"); |
|
172 } |
|
173 assert.equal(true, threw, |
|
174 "Assert.throws with an explicit error is eating extra errors", |
|
175 ns.Assert.AssertionError); |
|
176 threw = false; |
|
177 |
|
178 function ifError(err) { |
|
179 if (err) { |
|
180 throw err; |
|
181 } |
|
182 } |
|
183 assert.throws(function() { |
|
184 ifError(new Error("test error")); |
|
185 }); |
|
186 |
|
187 // make sure that validating using constructor really works |
|
188 threw = false; |
|
189 try { |
|
190 assert.throws( |
|
191 function() { |
|
192 throw ({}); |
|
193 }, |
|
194 Array |
|
195 ); |
|
196 } catch (e) { |
|
197 threw = true; |
|
198 } |
|
199 assert.ok(threw, "wrong constructor validation"); |
|
200 |
|
201 // use a RegExp to validate error message |
|
202 assert.throws(makeBlock(thrower, TypeError), /test/); |
|
203 |
|
204 // use a fn to validate error object |
|
205 assert.throws(makeBlock(thrower, TypeError), function(err) { |
|
206 if ((err instanceof TypeError) && /test/.test(err)) { |
|
207 return true; |
|
208 } |
|
209 }); |
|
210 |
|
211 // Make sure deepEqual doesn't loop forever on circular refs |
|
212 |
|
213 let b = {}; |
|
214 b.b = b; |
|
215 |
|
216 let c = {}; |
|
217 c.b = c; |
|
218 |
|
219 let gotError = false; |
|
220 try { |
|
221 assert.deepEqual(b, c); |
|
222 } catch (e) { |
|
223 gotError = true; |
|
224 } |
|
225 |
|
226 dump("All OK\n"); |
|
227 assert.ok(gotError); |
|
228 |
|
229 function testAssertionMessage(actual, expected) { |
|
230 try { |
|
231 assert.equal(actual, ""); |
|
232 } catch (e) { |
|
233 assert.equal(e.toString(), |
|
234 ["AssertionError:", expected, "==", '""'].join(" ")); |
|
235 } |
|
236 } |
|
237 testAssertionMessage(undefined, '"undefined"'); |
|
238 testAssertionMessage(null, "null"); |
|
239 testAssertionMessage(true, "true"); |
|
240 testAssertionMessage(false, "false"); |
|
241 testAssertionMessage(0, "0"); |
|
242 testAssertionMessage(100, "100"); |
|
243 testAssertionMessage(NaN, '"NaN"'); |
|
244 testAssertionMessage(Infinity, '"Infinity"'); |
|
245 testAssertionMessage(-Infinity, '"-Infinity"'); |
|
246 testAssertionMessage("", '""'); |
|
247 testAssertionMessage("foo", '"foo"'); |
|
248 testAssertionMessage([], "[]"); |
|
249 testAssertionMessage([1, 2, 3], "[1,2,3]"); |
|
250 testAssertionMessage(/a/, '"/a/"'); |
|
251 testAssertionMessage(/abc/gim, '"/abc/gim"'); |
|
252 testAssertionMessage(function f() {}, '"function f() {}"'); |
|
253 testAssertionMessage({}, "{}"); |
|
254 testAssertionMessage({a: undefined, b: null}, '{"a":"undefined","b":null}'); |
|
255 testAssertionMessage({a: NaN, b: Infinity, c: -Infinity}, |
|
256 '{"a":"NaN","b":"Infinity","c":"-Infinity"}'); |
|
257 |
|
258 // https://github.com/joyent/node/issues/2893 |
|
259 try { |
|
260 assert.throws(function () { |
|
261 ifError(null); |
|
262 }); |
|
263 } catch (e) { |
|
264 threw = true; |
|
265 assert.equal(e.message, "Missing expected exception.."); |
|
266 } |
|
267 assert.ok(threw); |
|
268 |
|
269 // https://github.com/joyent/node/issues/5292 |
|
270 try { |
|
271 assert.equal(1, 2); |
|
272 } catch (e) { |
|
273 assert.equal(e.toString().split("\n")[0], "AssertionError: 1 == 2") |
|
274 } |
|
275 |
|
276 try { |
|
277 assert.equal(1, 2, "oh no"); |
|
278 } catch (e) { |
|
279 assert.equal(e.toString().split("\n")[0], "AssertionError: oh no - 1 == 2") |
|
280 } |
|
281 |
|
282 // Export Assert.jsm methods to become globally accessible. |
|
283 export_assertions(); |
|
284 |
|
285 // Test XPCShell-test integration: |
|
286 ok(true, "OK, this went well"); |
|
287 deepEqual(/a/g, /a/g, "deep equal should work on RegExp"); |
|
288 deepEqual(/a/igm, /a/igm, "deep equal should work on RegExp"); |
|
289 deepEqual({a: 4, b: "1"}, {b: "1", a: 4}, "deep equal should work on regular Object"); |
|
290 deepEqual(a1, a2, "deep equal should work on Array with Object properties"); |
|
291 |
|
292 // Test robustness of reporting: |
|
293 equal(new ns.Assert.AssertionError({ |
|
294 actual: { |
|
295 toJSON: function() { |
|
296 throw "bam!"; |
|
297 } |
|
298 }, |
|
299 expected: "foo", |
|
300 operator: "=" |
|
301 }).message, "[object Object] = \"foo\""); |
|
302 } |