Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / remoting / webapp / base / js / base_unittest.js
blobc2812ad8a3361e772856bbf383f2b05ec65f32a3
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.
5 (function() {
7 'use strict';
9 QUnit.module('base');
11 QUnit.test('mix(dest, src) should copy properties from |src| to |dest|',
12 function(assert) {
13 var src = { a: 'a', b: 'b'};
14 var dest = { c: 'c'};
16 base.mix(dest, src);
17 assert.deepEqual(dest, {a: 'a', b: 'b', c: 'c'});
18 });
20 QUnit.test('mix(dest, src) should not override property.', function(assert) {
21 var src = { a: 'a', b: 'b'};
22 var dest = { a: 'a2'};
23 base.mix(dest, src);
24 assert.equal(dest['a'], 'a2');
25 assert.equal(dest['b'], 'b');
26 });
28 QUnit.test('values(obj) should return an array containing the values of |obj|',
29 function(assert) {
30 var output = base.values({ a: 'a', b: 'b'});
32 assert.notEqual(output.indexOf('a'), -1, '"a" should be in the output');
33 assert.notEqual(output.indexOf('b'), -1, '"b" should be in the output');
34 });
36 QUnit.test('deepCopy(obj) should return null on NaN and undefined',
37 function(assert) {
38 assert.equal(base.deepCopy(NaN), null);
39 assert.equal(base.deepCopy(undefined), null);
40 });
42 QUnit.test('deepCopy(obj) should copy primitive types recursively',
43 function(assert) {
44 assert.equal(base.deepCopy(1), 1);
45 assert.equal(base.deepCopy('hello'), 'hello');
46 assert.equal(base.deepCopy(false), false);
47 assert.equal(base.deepCopy(null), null);
48 assert.deepEqual(base.deepCopy([1, 2]), [1, 2]);
49 assert.deepEqual(base.deepCopy({'key': 'value'}), {'key': 'value'});
50 assert.deepEqual(base.deepCopy(
51 {'key': {'key_nested': 'value_nested'}}),
52 {'key': {'key_nested': 'value_nested'}}
54 assert.deepEqual(base.deepCopy([1, [2, [3]]]), [1, [2, [3]]]);
55 });
57 QUnit.test('modify the original after deepCopy(obj) should not affect the copy',
58 function(assert) {
59 var original = [1, 2, 3, 4];
60 var copy = base.deepCopy(original);
61 original[2] = 1000;
62 assert.deepEqual(copy, [1, 2, 3, 4]);
63 });
65 QUnit.test('dispose(obj) should invoke the dispose method on |obj|',
66 function(assert) {
67 /**
68 * @constructor
69 * @implements {base.Disposable}
71 base.MockDisposable = function() {};
72 base.MockDisposable.prototype.dispose = sinon.spy();
74 var obj = new base.MockDisposable();
75 base.dispose(obj);
76 sinon.assert.called(obj.dispose);
77 });
79 QUnit.test('dispose(obj) should not crash if |obj| is null',
80 function(assert) {
81 assert.expect(0);
82 base.dispose(null);
83 });
85 QUnit.test(
86 'urljoin(url, opt_param) should return url if |opt_param| is missing',
87 function(assert) {
88 assert.equal(
89 base.urlJoin('http://www.chromium.org'), 'http://www.chromium.org');
90 });
92 QUnit.test('urljoin(url, opt_param) should urlencode |opt_param|',
93 function(assert) {
94 var result = base.urlJoin('http://www.chromium.org', {
95 a: 'a',
96 foo: 'foo',
97 escapist: ':/?#[]@$&+,;='
98 });
99 assert.equal(
100 result,
101 'http://www.chromium.org?a=a&foo=foo' +
102 '&escapist=%3A%2F%3F%23%5B%5D%40%24%26%2B%2C%3B%3D');
105 QUnit.test('escapeHTML(str) should escape special characters', function(assert){
106 assert.equal(
107 base.escapeHTML('<script>alert("hello")</script>'),
108 '&lt;script&gt;alert("hello")&lt;/script&gt;');
111 QUnit.test('Promise.sleep(delay) should fulfill the promise after |delay|',
113 * 'this' is not defined for jscompile, so it can't figure out the type of
114 * this.clock.
115 * @suppress {reportUnknownTypes|checkVars|checkTypes}
117 function(assert) {
118 var isCalled = false;
119 var clock = /** @type {QUnit.Clock} */ (this.clock);
121 var promise = base.Promise.sleep(100).then(function(){
122 isCalled = true;
123 assert.ok(true, 'Promise.sleep() is fulfilled after delay.');
126 // Tick the clock for 2 seconds and check if the promise is fulfilled.
127 clock.tick(2);
129 // Promise fulfillment always occur on a new stack. Therefore, we will run
130 // the verification in a requestAnimationFrame.
131 window.requestAnimationFrame(function(){
132 assert.ok(
133 !isCalled, 'Promise.sleep() should not be fulfilled prematurely.');
134 clock.tick(101);
137 return promise;
140 QUnit.test('Promise.negate should fulfill iff the promise does not.',
141 function(assert) {
142 return base.Promise.negate(Promise.reject())
143 .then(function() {
144 assert.ok(true);
145 }).catch(function() {
146 assert.ok(false);
147 }).then(function() {
148 return base.Promise.negate(Promise.resolve());
149 }).then(function() {
150 assert.ok(false);
151 }).catch(function() {
152 assert.ok(true);
156 QUnit.module('base.Deferred');
158 QUnit.test('resolve() should fulfill the underlying promise.', function(assert){
159 /** @returns {Promise} */
160 function async() {
161 var deferred = new base.Deferred();
162 deferred.resolve('bar');
163 return deferred.promise();
166 return async().then(function(/** string */ value){
167 assert.equal(value, 'bar');
168 }, function() {
169 assert.ok(false, 'The reject handler should not be invoked.');
173 QUnit.test('reject() should fail the underlying promise.', function(assert) {
174 /** @returns {Promise} */
175 function async() {
176 var deferred = new base.Deferred();
177 deferred.reject('bar');
178 return deferred.promise();
181 return async().then(function(){
182 assert.ok(false, 'The then handler should not be invoked.');
183 }, function(value) {
184 assert.equal(value, 'bar');
189 /** @type {base.EventSourceImpl} */
190 var source = null;
191 var listener = null;
193 QUnit.module('base.EventSource', {
194 beforeEach: function() {
195 source = new base.EventSourceImpl();
196 source.defineEvents(['foo', 'bar']);
197 listener = sinon.spy();
198 source.addEventListener('foo', listener);
200 afterEach: function() {
201 source = null;
202 listener = null;
206 QUnit.test('raiseEvent() should invoke the listener', function() {
207 source.raiseEvent('foo');
208 sinon.assert.called(listener);
211 QUnit.test(
212 'raiseEvent() should invoke the listener with the correct event data',
213 function(assert) {
214 var data = {
215 field: 'foo'
217 source.raiseEvent('foo', data);
218 sinon.assert.calledWith(listener, data);
221 QUnit.test(
222 'raiseEvent() should not invoke listeners that are added during raiseEvent',
223 function(assert) {
224 source.addEventListener('foo', function() {
225 source.addEventListener('foo', function() {
226 assert.ok(false);
228 assert.ok(true);
230 source.raiseEvent('foo');
233 QUnit.test('raiseEvent() should not invoke listeners of a different event',
234 function(assert) {
235 source.raiseEvent('bar');
236 sinon.assert.notCalled(listener);
239 QUnit.test('raiseEvent() should assert when undeclared events are raised',
240 function(assert) {
241 sinon.stub(base.debug, 'assert');
242 try {
243 source.raiseEvent('undefined');
244 } catch (e) {
245 } finally {
246 sinon.assert.called(base.debug.assert);
247 $testStub(base.debug.assert).restore();
251 QUnit.test(
252 'removeEventListener() should not invoke the listener in subsequent ' +
253 'calls to |raiseEvent|',
254 function(assert) {
255 source.raiseEvent('foo');
256 sinon.assert.calledOnce(listener);
258 source.removeEventListener('foo', listener);
259 source.raiseEvent('foo');
260 sinon.assert.calledOnce(listener);
263 QUnit.test('removeEventListener() should work even if the listener ' +
264 'is removed during |raiseEvent|',
265 function(assert) {
266 var sink = {};
267 sink.listener = sinon.spy(function() {
268 source.removeEventListener('foo', sink.listener);
271 source.addEventListener('foo', sink.listener);
272 source.raiseEvent('foo');
273 sinon.assert.calledOnce(sink.listener);
275 source.raiseEvent('foo');
276 sinon.assert.calledOnce(sink.listener);
279 QUnit.test('encodeUtf8() can encode UTF8 strings', function(assert) {
280 /** @type {function(ArrayBuffer):Array} */
281 function toJsArray(arrayBuffer) {
282 var result = [];
283 var array = new Uint8Array(arrayBuffer);
284 for (var i = 0; i < array.length; ++i) {
285 result.push(array[i]);
287 return result;
290 // ASCII.
291 assert.deepEqual(toJsArray(base.encodeUtf8("ABC")), [0x41, 0x42, 0x43]);
293 // Some arbitrary characters from the basic Unicode plane.
294 assert.deepEqual(
295 toJsArray(base.encodeUtf8("挂Ѓф")),
296 [/* 挂 */ 0xE6, 0x8C, 0x82, /* Ѓ */ 0xD0, 0x83, /* ф */ 0xD1, 0x84]);
298 // Unicode surrogate pair for U+1F603.
299 assert.deepEqual(toJsArray(base.encodeUtf8("😃")),
300 [0xF0, 0x9F, 0x98, 0x83]);
303 QUnit.test('decodeUtf8() can decode UTF8 strings', function(assert) {
304 // ASCII.
305 assert.equal(base.decodeUtf8(new Uint8Array([0x41, 0x42, 0x43]).buffer),
306 "ABC");
308 // Some arbitrary characters from the basic Unicode plane.
309 assert.equal(
310 base.decodeUtf8(
311 new Uint8Array([/* 挂 */ 0xE6, 0x8C, 0x82,
312 /* Ѓ */ 0xD0, 0x83,
313 /* ф */ 0xD1, 0x84]).buffer),
314 "挂Ѓф");
316 // Unicode surrogate pair for U+1F603.
317 assert.equal(base.decodeUtf8(new Uint8Array([0xF0, 0x9F, 0x98, 0x83]).buffer),
318 "😃");
321 })();