OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 (function() { | |
6 | |
7 'use strict'; | |
8 | |
9 module('base'); | |
10 | |
11 test('mix(dest, src) should copy properties from |src| to |dest|', | |
12 function() { | |
13 var src = { a: 'a', b: 'b'}; | |
14 var dest = { c: 'c'}; | |
15 | |
16 base.mix(dest, src); | |
17 deepEqual(dest, {a: 'a', b: 'b', c: 'c'}); | |
18 }); | |
19 | |
20 test('mix(dest, src) should assert if properties are overwritten', | |
21 function() { | |
22 var src = { a: 'a', b: 'b'}; | |
23 var dest = { a: 'a'}; | |
24 | |
25 sinon.stub(base.debug, 'assert'); | |
26 | |
27 try { | |
28 base.mix(dest, src); | |
29 } catch (e) { | |
30 } finally { | |
31 sinon.assert.called(base.debug.assert); | |
32 $testStub(base.debug.assert).restore(); | |
33 } | |
34 }); | |
35 | |
36 test('values(obj) should return an array containing the values of |obj|', | |
37 function() { | |
38 var output = base.values({ a: 'a', b: 'b'}); | |
39 | |
40 notEqual(output.indexOf('a'), -1, '"a" should be in the output'); | |
41 notEqual(output.indexOf('b'), -1, '"b" should be in the output'); | |
42 }); | |
43 | |
44 test('deepCopy(obj) should return null on NaN and undefined', | |
45 function() { | |
46 QUnit.equal(base.deepCopy(NaN), null); | |
47 QUnit.equal(base.deepCopy(undefined), null); | |
48 }); | |
49 | |
50 test('deepCopy(obj) should copy primitive types recursively', | |
51 function() { | |
52 QUnit.equal(base.deepCopy(1), 1); | |
53 QUnit.equal(base.deepCopy('hello'), 'hello'); | |
54 QUnit.equal(base.deepCopy(false), false); | |
55 QUnit.equal(base.deepCopy(null), null); | |
56 QUnit.deepEqual(base.deepCopy([1, 2]), [1, 2]); | |
57 QUnit.deepEqual(base.deepCopy({'key': 'value'}), {'key': 'value'}); | |
58 QUnit.deepEqual(base.deepCopy( | |
59 {'key': {'key_nested': 'value_nested'}}), | |
60 {'key': {'key_nested': 'value_nested'}} | |
61 ); | |
62 QUnit.deepEqual(base.deepCopy([1, [2, [3]]]), [1, [2, [3]]]); | |
63 }); | |
64 | |
65 test('modify the original after deepCopy(obj) should not affect the copy', | |
66 function() { | |
67 var original = [1, 2, 3, 4]; | |
68 var copy = base.deepCopy(original); | |
69 original[2] = 1000; | |
70 QUnit.deepEqual(copy, [1, 2, 3, 4]); | |
71 }); | |
72 | |
73 test('dispose(obj) should invoke the dispose method on |obj|', | |
74 function() { | |
75 /** | |
76 * @constructor | |
77 * @implements {base.Disposable} | |
78 */ | |
79 base.MockDisposable = function() {}; | |
80 base.MockDisposable.prototype.dispose = sinon.spy(); | |
81 | |
82 var obj = new base.MockDisposable(); | |
83 base.dispose(obj); | |
84 sinon.assert.called(obj.dispose); | |
85 }); | |
86 | |
87 test('dispose(obj) should not crash if |obj| is null', | |
88 function() { | |
89 expect(0); | |
90 base.dispose(null); | |
91 }); | |
92 | |
93 test('urljoin(url, opt_param) should return url if |opt_param| is missing', | |
94 function() { | |
95 QUnit.equal( | |
96 base.urlJoin('http://www.chromium.org'), 'http://www.chromium.org'); | |
97 }); | |
98 | |
99 test('urljoin(url, opt_param) should urlencode |opt_param|', | |
100 function() { | |
101 var result = base.urlJoin('http://www.chromium.org', { | |
102 a: 'a', | |
103 foo: 'foo', | |
104 escapist: ':/?#[]@$&+,;=' | |
105 }); | |
106 QUnit.equal( | |
107 result, | |
108 'http://www.chromium.org?a=a&foo=foo' + | |
109 '&escapist=%3A%2F%3F%23%5B%5D%40%24%26%2B%2C%3B%3D'); | |
110 }); | |
111 | |
112 test('escapeHTML(str) should escape special characters', function() { | |
113 QUnit.equal( | |
114 base.escapeHTML('<script>alert("hello")</script>'), | |
115 '<script>alert("hello")</script>'); | |
116 }); | |
117 | |
118 QUnit.asyncTest('Promise.sleep(delay) should fulfill the promise after |delay|', | |
119 /** | |
120 * 'this' is not defined for jscompile, so it can't figure out the type of | |
121 * this.clock. | |
122 * @suppress {reportUnknownTypes|checkVars|checkTypes} | |
123 */ | |
124 function() { | |
125 var isCalled = false; | |
126 var clock = /** @type {QUnit.Clock} */ (this.clock); | |
127 | |
128 base.Promise.sleep(100).then(function(){ | |
129 isCalled = true; | |
130 ok(true, 'Promise.sleep() is fulfilled after delay.'); | |
131 QUnit.start(); | |
132 }); | |
133 | |
134 // Tick the clock for 2 seconds and check if the promise is fulfilled. | |
135 clock.tick(2); | |
136 | |
137 // Promise fulfillment always occur on a new stack. Therefore, we will run | |
138 // the verification in a requestAnimationFrame. | |
139 window.requestAnimationFrame(function(){ | |
140 ok(!isCalled, 'Promise.sleep() should not be fulfilled prematurely.'); | |
141 clock.tick(101); | |
142 }); | |
143 }); | |
144 | |
145 QUnit.asyncTest('Promise.negate should fulfill iff the promise does not.', | |
146 function() { | |
147 | |
148 base.Promise.negate(Promise.reject()).then( | |
149 QUnit.ok.bind(null, true), | |
150 /** @type {Function} */ (QUnit.ok.bind(null, false))); | |
151 base.Promise.negate(Promise.resolve()).then( | |
152 QUnit.ok.bind(null, false), | |
153 /** @type {Function} */ (QUnit.ok.bind(null, true))); | |
154 window.requestAnimationFrame(function(){ | |
155 QUnit.start(); | |
156 }); | |
157 }); | |
158 | |
159 module('base.Deferred'); | |
160 | |
161 QUnit.asyncTest('resolve() should fulfill the underlying promise.', function() { | |
162 /** @returns {Promise} */ | |
163 function async() { | |
164 var deferred = new base.Deferred(); | |
165 deferred.resolve('bar'); | |
166 return deferred.promise(); | |
167 } | |
168 | |
169 async().then( | |
170 /** @param {string} value */ | |
171 function(value){ | |
172 QUnit.equal(value, 'bar'); | |
173 QUnit.start(); | |
174 }, function() { | |
175 QUnit.ok(false, 'The reject handler should not be invoked.'); | |
176 }); | |
177 }); | |
178 | |
179 QUnit.asyncTest('reject() should fail the underlying promise.', function() { | |
180 /** @returns {Promise} */ | |
181 function async() { | |
182 var deferred = new base.Deferred(); | |
183 deferred.reject('bar'); | |
184 return deferred.promise(); | |
185 } | |
186 | |
187 async().then(function(){ | |
188 QUnit.ok(false, 'The then handler should not be invoked.'); | |
189 }, function(value) { | |
190 QUnit.equal(value, 'bar'); | |
191 QUnit.start(); | |
192 }); | |
193 }); | |
194 | |
195 | |
196 /** @type {base.EventSourceImpl} */ | |
197 var source = null; | |
198 var listener = null; | |
199 | |
200 module('base.EventSource', { | |
201 setup: function() { | |
202 source = new base.EventSourceImpl(); | |
203 source.defineEvents(['foo', 'bar']); | |
204 listener = sinon.spy(); | |
205 source.addEventListener('foo', listener); | |
206 }, | |
207 teardown: function() { | |
208 source = null; | |
209 listener = null; | |
210 } | |
211 }); | |
212 | |
213 test('raiseEvent() should invoke the listener', function() { | |
214 source.raiseEvent('foo'); | |
215 sinon.assert.called(listener); | |
216 }); | |
217 | |
218 test('raiseEvent() should invoke the listener with the correct event data', | |
219 function() { | |
220 var data = { | |
221 field: 'foo' | |
222 }; | |
223 source.raiseEvent('foo', data); | |
224 sinon.assert.calledWith(listener, data); | |
225 }); | |
226 | |
227 test( | |
228 'raiseEvent() should not invoke listeners that are added during raiseEvent', | |
229 function() { | |
230 source.addEventListener('foo', function() { | |
231 source.addEventListener('foo', function() { | |
232 ok(false); | |
233 }); | |
234 ok(true); | |
235 }); | |
236 source.raiseEvent('foo'); | |
237 }); | |
238 | |
239 test('raiseEvent() should not invoke listeners of a different event', | |
240 function() { | |
241 source.raiseEvent('bar'); | |
242 sinon.assert.notCalled(listener); | |
243 }); | |
244 | |
245 test('raiseEvent() should assert when undeclared events are raised', | |
246 function() { | |
247 sinon.stub(base.debug, 'assert'); | |
248 try { | |
249 source.raiseEvent('undefined'); | |
250 } catch (e) { | |
251 } finally { | |
252 sinon.assert.called(base.debug.assert); | |
253 $testStub(base.debug.assert).restore(); | |
254 } | |
255 }); | |
256 | |
257 test( | |
258 'removeEventListener() should not invoke the listener in subsequent ' + | |
259 'calls to |raiseEvent|', | |
260 function() { | |
261 source.raiseEvent('foo'); | |
262 sinon.assert.calledOnce(listener); | |
263 | |
264 source.removeEventListener('foo', listener); | |
265 source.raiseEvent('foo'); | |
266 sinon.assert.calledOnce(listener); | |
267 }); | |
268 | |
269 test('removeEventListener() should work even if the listener ' + | |
270 'is removed during |raiseEvent|', | |
271 function() { | |
272 var sink = {}; | |
273 sink.listener = sinon.spy(function() { | |
274 source.removeEventListener('foo', sink.listener); | |
275 }); | |
276 | |
277 source.addEventListener('foo', sink.listener); | |
278 source.raiseEvent('foo'); | |
279 sinon.assert.calledOnce(sink.listener); | |
280 | |
281 source.raiseEvent('foo'); | |
282 sinon.assert.calledOnce(sink.listener); | |
283 }); | |
284 | |
285 test('encodeUtf8() can encode UTF8 strings', function() { | |
286 /** @type {function(ArrayBuffer):Array} */ | |
287 function toJsArray(arrayBuffer) { | |
288 var result = []; | |
289 var array = new Uint8Array(arrayBuffer); | |
290 for (var i = 0; i < array.length; ++i) { | |
291 result.push(array[i]); | |
292 } | |
293 return result; | |
294 } | |
295 | |
296 // ASCII. | |
297 QUnit.deepEqual(toJsArray(base.encodeUtf8("ABC")), [0x41, 0x42, 0x43]); | |
298 | |
299 // Some arbitrary characters from the basic Unicode plane. | |
300 QUnit.deepEqual( | |
301 toJsArray(base.encodeUtf8("挂Ѓф")), | |
302 [/* 挂 */ 0xE6, 0x8C, 0x82, /* Ѓ */ 0xD0, 0x83, /* ф */ 0xD1, 0x84]); | |
303 | |
304 // Unicode surrogate pair for U+1F603. | |
305 QUnit.deepEqual(toJsArray(base.encodeUtf8("😃")), | |
306 [0xF0, 0x9F, 0x98, 0x83]); | |
307 }); | |
308 | |
309 test('decodeUtf8() can decode UTF8 strings', function() { | |
310 // ASCII. | |
311 QUnit.equal(base.decodeUtf8(new Uint8Array([0x41, 0x42, 0x43]).buffer), | |
312 "ABC"); | |
313 | |
314 // Some arbitrary characters from the basic Unicode plane. | |
315 QUnit.equal( | |
316 base.decodeUtf8( | |
317 new Uint8Array([/* 挂 */ 0xE6, 0x8C, 0x82, | |
318 /* Ѓ */ 0xD0, 0x83, | |
319 /* ф */ 0xD1, 0x84]).buffer), | |
320 "挂Ѓф"); | |
321 | |
322 // Unicode surrogate pair for U+1F603. | |
323 QUnit.equal(base.decodeUtf8(new Uint8Array([0xF0, 0x9F, 0x98, 0x83]).buffer), | |
324 "😃"); | |
325 }); | |
326 | |
327 })(); | |
OLD | NEW |