Home | History | Annotate | Download | only in unittests
      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.spy(base.debug, 'assert');
     26 
     27     try {
     28       base.mix(dest, src);
     29     } catch (e) {
     30     } finally {
     31       sinon.assert.called(base.debug.assert);
     32       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('dispose(obj) should invoke the dispose method on |obj|',
     45   function() {
     46     var obj = {
     47       dispose: sinon.spy()
     48     };
     49     base.dispose(obj);
     50     sinon.assert.called(obj.dispose);
     51 });
     52 
     53 test('dispose(obj) should not crash if |obj| is null',
     54   function() {
     55     expect(0);
     56     base.dispose(null);
     57 });
     58 
     59 test('urljoin(url, opt_param) should return url if |opt_param| is missing',
     60   function() {
     61     QUnit.equal(
     62         base.urlJoin('http://www.chromium.org'), 'http://www.chromium.org');
     63 });
     64 
     65 test('urljoin(url, opt_param) should urlencode |opt_param|',
     66   function() {
     67     var result = base.urlJoin('http://www.chromium.org', {
     68       a: 'a',
     69       foo: 'foo',
     70       escapist: ':/?#[]@$&+,;='
     71     });
     72     QUnit.equal(
     73         result,
     74         'http://www.chromium.org?a=a&foo=foo' +
     75         '&escapist=%3A%2F%3F%23%5B%5D%40%24%26%2B%2C%3B%3D');
     76 });
     77 
     78 test('escapeHTML(str) should escape special characters', function() {
     79   QUnit.equal(
     80     base.escapeHTML('<script>alert("hello")</script>'),
     81     '&lt;script&gt;alert("hello")&lt;/script&gt;');
     82 });
     83 
     84 QUnit.asyncTest('Promise.sleep(delay) should fulfill the promise after |delay|',
     85   function() {
     86     var isCalled = false;
     87     var clock = this.clock;
     88 
     89     base.Promise.sleep(100).then(function(){
     90       isCalled = true;
     91       ok(true, 'Promise.sleep() is fulfilled after delay.');
     92       QUnit.start();
     93     });
     94 
     95     // Tick the clock for 2 seconds and check if the promise is fulfilled.
     96     clock.tick(2);
     97 
     98     // Promise fulfillment always occur on a new stack.  Therefore, we will run
     99     // the verification in a requestAnimationFrame.
    100     window.requestAnimationFrame(function(){
    101       ok(!isCalled, 'Promise.sleep() should not be fulfilled prematurely.');
    102       clock.tick(101);
    103     }.bind(this));
    104 });
    105 
    106 QUnit.asyncTest('Promise.negate should fulfill iff the promise does not.',
    107   function() {
    108 
    109     base.Promise.negate(Promise.reject()).then(
    110         ok.bind(null, true),
    111         ok.bind(null, false));
    112     base.Promise.negate(Promise.resolve()).then(
    113         ok.bind(null, false),
    114         ok.bind(null, true));
    115     window.requestAnimationFrame(function(){
    116       QUnit.start();
    117     });
    118 });
    119 
    120 module('base.Deferred');
    121 
    122 QUnit.asyncTest('resolve() should fulfill the underlying promise.', function() {
    123   function async() {
    124     var deferred = new base.Deferred();
    125     deferred.resolve('bar');
    126     return deferred.promise();
    127   }
    128 
    129   async().then(function(value){
    130     QUnit.equal(value, 'bar');
    131     QUnit.start();
    132   }, function() {
    133     QUnit.ok(false, 'The reject handler should not be invoked.');
    134   });
    135 });
    136 
    137 QUnit.asyncTest('reject() should fail the underlying promise.', function() {
    138   function async() {
    139     var deferred = new base.Deferred();
    140     deferred.reject('bar');
    141     return deferred.promise();
    142   }
    143 
    144   async().then(function(){
    145     QUnit.ok(false, 'The then handler should not be invoked.');
    146   }, function(value) {
    147     QUnit.equal(value, 'bar');
    148     QUnit.start();
    149   });
    150 });
    151 
    152 
    153 var source = null;
    154 var listener = null;
    155 
    156 module('base.EventSource', {
    157   setup: function() {
    158     source = new base.EventSource();
    159     source.defineEvents(['foo', 'bar']);
    160     listener = sinon.spy();
    161     source.addEventListener('foo', listener);
    162   },
    163   teardown: function() {
    164     source = null;
    165     listener = null;
    166   }
    167 });
    168 
    169 test('raiseEvent() should invoke the listener', function() {
    170   source.raiseEvent('foo');
    171   sinon.assert.called(listener);
    172 });
    173 
    174 test('raiseEvent() should invoke the listener with the correct event data',
    175   function() {
    176     var data = {
    177       field: 'foo'
    178     };
    179     source.raiseEvent('foo', data);
    180     sinon.assert.calledWith(listener, data);
    181 });
    182 
    183 test(
    184   'raiseEvent() should not invoke listeners that are added during raiseEvent',
    185   function() {
    186     source.addEventListener('foo', function() {
    187       source.addEventListener('foo', function() {
    188         ok(false);
    189       });
    190       ok(true);
    191     });
    192     source.raiseEvent('foo');
    193 });
    194 
    195 test('raiseEvent() should not invoke listeners of a different event',
    196   function() {
    197     source.raiseEvent('bar');
    198     sinon.assert.notCalled(listener);
    199 });
    200 
    201 test('raiseEvent() should assert when undeclared events are raised',
    202   function() {
    203     sinon.spy(base.debug, 'assert');
    204     try {
    205       source.raiseEvent('undefined');
    206     } catch (e) {
    207     } finally {
    208       sinon.assert.called(base.debug.assert);
    209       base.debug.assert.restore();
    210     }
    211 });
    212 
    213 test(
    214   'removeEventListener() should not invoke the listener in subsequent ' +
    215   'calls to |raiseEvent|',
    216   function() {
    217     source.raiseEvent('foo');
    218     sinon.assert.calledOnce(listener);
    219 
    220     source.removeEventListener('foo', listener);
    221     source.raiseEvent('foo');
    222     sinon.assert.calledOnce(listener);
    223 });
    224 
    225 test('removeEventListener() should work even if the listener ' +
    226   'is removed during |raiseEvent|',
    227   function() {
    228     var sink = {};
    229     sink.listener = sinon.spy(function() {
    230       source.removeEventListener('foo', sink.listener);
    231     });
    232 
    233     source.addEventListener('foo', sink.listener);
    234     source.raiseEvent('foo');
    235     sinon.assert.calledOnce(sink.listener);
    236 
    237     source.raiseEvent('foo');
    238     sinon.assert.calledOnce(sink.listener);
    239 });
    240 
    241 test('encodeUtf8() can encode UTF8 strings', function() {
    242   function toJsArray(arrayBuffer) {
    243     var result = [];
    244     var array = new Uint8Array(arrayBuffer);
    245     for (var i = 0; i < array.length; ++i) {
    246       result.push(array[i]);
    247     }
    248     return result;
    249   }
    250 
    251   // ASCII.
    252   QUnit.deepEqual(toJsArray(base.encodeUtf8("ABC")), [0x41, 0x42, 0x43]);
    253 
    254   // Some arbitrary characters from the basic Unicode plane.
    255   QUnit.deepEqual(
    256       toJsArray(base.encodeUtf8("")),
    257       [/*  */ 0xE6, 0x8C, 0x82, /*  */ 0xD0, 0x83, /*  */ 0xD1, 0x84]);
    258 
    259   // Unicode surrogate pair for U+1F603.
    260   QUnit.deepEqual(toJsArray(base.encodeUtf8("")),
    261                   [0xF0, 0x9F, 0x98, 0x83]);
    262 });
    263 
    264 test('decodeUtf8() can decode UTF8 strings', function() {
    265   // ASCII.
    266   QUnit.equal(base.decodeUtf8(new Uint8Array([0x41, 0x42, 0x43]).buffer),
    267               "ABC");
    268 
    269   // Some arbitrary characters from the basic Unicode plane.
    270   QUnit.equal(
    271       base.decodeUtf8(
    272           new Uint8Array([/*  */ 0xE6, 0x8C, 0x82,
    273                           /*  */ 0xD0, 0x83,
    274                           /*  */ 0xD1, 0x84]).buffer),
    275       "");
    276 
    277   // Unicode surrogate pair for U+1F603.
    278   QUnit.equal(base.decodeUtf8(new Uint8Array([0xF0, 0x9F, 0x98, 0x83]).buffer),
    279               "");
    280 });
    281 
    282 })();
    283