/// export import mocha = require('../../test/mocha'); var expect = mocha.chai.expect; var mock = mocha.mock; var rcsdk = mocha.rcsdk; describe('RCSDK.core.Utils', function() { 'use strict'; var Utils = rcsdk.getUtils(); describe('parseQueryString & queryStringify', function() { it('parses queryStrings', function() { expect(Utils.parseQueryString('foo=bar&bar=baz')).to.deep.equal({foo: 'bar', bar: 'baz'}); expect(Utils.parseQueryString('foo=bar&foo=baz')).to.deep.equal({foo: ['bar', 'baz']}); expect(Utils.parseQueryString('foo')).to.deep.equal({foo: true}); }); it('builds queryStrings', function() { expect(Utils.queryStringify({foo: 'bar', bar: 'baz'})).to.equal('foo=bar&bar=baz'); expect(Utils.queryStringify({foo: ['bar', 'baz']})).to.equal('foo=bar&foo=baz'); }); it('decodes pre-encoded string representation of object to be equal to original object', function() { function encodeDecode(v) { return Utils.parseQueryString(Utils.queryStringify(v)); } var simple = {foo: 'bar'}, array = {foo: ['bar', 'baz']}; expect(encodeDecode(simple)).to.deep.equal(simple); expect(encodeDecode(array)).to.deep.equal(array); }); }); describe('extend', function() { it('applies properties of sources to target (only first level)', function() { var target = { foo: { id: 0, name: 'name' } }, source1 = { foo: { id: 1 }, bar: { id: 1 } }, source2 = { foo: { id: 2 } }, result = Utils.extend(target, source1, source2); // make sure result is target expect(result).to.equal(target); // make sure source2 has overrided source1 and target expect(result.foo.id).to.equal(2); expect(result.foo.name).to.be.an('undefined'); // make sure other properties of source 1 are copied expect(result.bar.id).to.equal(1); }); it('applies all properties of sources to target in deep mode', function() { var target = { foo: { id: 0, name: 'name' } }, source1 = { foo: { id: 1 }, bar: { id: 1 } }, source2 = { foo: { id: 2 } }, result = Utils.extend(true, target, source1, source2); // make sure result is target expect(result).to.equal(target); // make sure original target properties that does not exist in sources are still available expect(result.foo.name).to.equal('name'); // make sure source2 has overrided source1 and target expect(result.foo.id).to.equal(2); // make sure other properties of source 1 are copied expect(result.bar.id).to.equal(1); }); it('copies all kinds of values', function() { var target = { 'array': [] }, source = { 'object': { bar: { baz: 'baz' } }, 'null': null, 'array': [1, 2, 3], 'date': new Date(), 'string': 'string' }; Utils.extend(true, target, source); // Deep equality expect(target).to.deep.equal(source); // Dates are linked expect(target.date).to.equal(source.date); // Arrays are cloned expect(target.array).not.to.equal(source.array); }); }); describe('poll & stopPolling', function() { it('allows to set custom delay', function(done) { Utils.poll(function(next, delay) { expect(delay).to.equal(10); done(); }, 10); }); it('provides a method to do it continuously', function(done) { var i = 0; Utils.poll(function(next) { i++; if (i < 3) next(); else done(); }, 1); after(function() { expect(i).to.equal(3); }); }); it('provides a method stop', function(done) { var timeout = Utils.poll(function(next) { done(new Error('This should never be reached')); }, 10); Utils.stopPolling(timeout); done(); }); it('cancels a previous timeout if provided', function(done) { var timeout = Utils.poll(function(next) { done(new Error('This should never be reached')); }, 10); var timeout2 = Utils.poll(function(next) { done(); }, 10, timeout); }); }); describe('parseNumber', function() { it('extracts object itself as number if no options given', function() { expect(Utils.parseNumber(1)).to.equal(1); expect(Utils.parseNumber('1')).to.equal(1); expect(Utils.parseNumber('0')).to.equal(0); expect(Utils.parseNumber([])).to.equal(0); expect(Utils.parseNumber([1])).to.equal(1); expect(Utils.parseNumber([1, 1])).to.equal(1); expect(Utils.parseNumber('not-a-number')).to.equal(0); expect(Utils.parseNumber(null)).to.equal(0); }); }); describe('stringExtractor', function() { it('extracts object itself as string if no options given', function() { expect(Utils.parseString(1)).to.equal('1'); expect(Utils.parseString(0)).to.equal(''); expect(Utils.parseString([])).to.equal(''); expect(Utils.parseString([1, 2])).to.equal('1,2'); expect(Utils.parseString(null)).to.equal(''); expect(Utils.parseString({})).to.equal('[object Object]'); }); }); describe('isEmail', function() { function emailValidator(description, multiple, valueToTest, expectedValidationResult) { it(description, function() { expect(Utils.isEmail(valueToTest, multiple)).to.equal(expectedValidationResult); }); } describe('positive tests', function() { emailValidator('should validate simple addresses', false, 'foo@bar.com', true); emailValidator('should validate addresses with digits', false, '123@456.789', true); emailValidator('should validate addresses with special characters', false, '!#$%&\'*+/=?^_`{|}~-@qux.com', true); emailValidator('should validate addresses with multiple host segments', false, 'foo@bar.baz.qux.com', true); emailValidator('should validate multiple addresses when true is specified for the multiple constructor argument', true, 'foo@bar.com; baz@qux.com', true); }); describe('negative tests', function() { emailValidator('should not validate addresses with multiple @ symbols', false, 'foo@bar@baz.com', false); emailValidator('should not validate addresses with invalid characters', false, 'foo bar@baz.com', false); emailValidator('should not validate addresses with malformed host segment', false, 'foo@bar.baz.', false); emailValidator('should not validate addresses with missing host segment', false, 'foo@', false); emailValidator('should not validate multiple addresses when false is specified for the multiple constructor argument', false, 'foo@bar.com; baz@qux.com', false); }); }); describe('isPhone', function() { function phoneValidator(description, valueToTest, expectedValidationResult) { it(description, function() { expect(Utils.isPhoneNumber(valueToTest)).to.equal(expectedValidationResult); }); } describe('positive tests', function() { phoneValidator('should validate a phone number with no formatting characters', '16501234567', true); phoneValidator('should validate a phone number with typical formatting characters', '1 (650) 123-4567', true); phoneValidator('should validate a phone number with periods as digit separators', '1.650.123.4567', true); phoneValidator('should validate a phone number with optional + prefix', '+1 650 123 4567', true); phoneValidator('should validate a vanity phone number', '+1 800 FOR HELP', true); }); describe('negative tests', function() { phoneValidator('should not validate a phone number that is missing the country code', '(650) 123-4567', false); phoneValidator('should not validate a phone number that has too few digits', '1 (650) 123-456', false); phoneValidator('should not validate a phone number with letters in area code', '+1 FOO FOR HELP', false); }); }); describe('is*', function() { describe('isDate', function() { expect(Utils.isDate(new Date())).to.equal(true); }); describe('isFunction', function() { expect(Utils.isFunction(Date)).to.equal(true); expect(Utils.isFunction(function() {})).to.equal(true); }); describe('isArray', function() { expect(Utils.isArray([])).to.equal(true); }); describe('isNaN', function() { expect(Utils.isNaN(NaN)).to.equal(true); }); }); describe('getProperty', function() { it('returns a nested property', function() { var foo = { bar: { baz: 'qux' }, arr: ['zero', 'one', 'two', {foo: 'bar'}] }; expect(Utils.getProperty(foo, 'bar.baz')).to.equal('qux'); expect(Utils.getProperty(foo, 'arr[0]')).to.equal('zero'); expect(Utils.getProperty(foo, 'arr[1]')).to.equal('one'); expect(Utils.getProperty(foo, 'arr[3].foo')).to.equal('bar'); expect(Utils.getProperty(foo, 'nonexistent')).to.equal(undefined); }); }); });