dojo
Version:
Dojo core is a powerful, lightweight library that makes common tasks quicker and easier. Animate elements, manipulate the DOM, and query with easy CSS syntax, all without sacrificing performance.
414 lines (350 loc) • 11.2 kB
JavaScript
define([
'intern!object',
'intern/chai!assert',
'dojo/_base/array',
'../../../_base/lang',
'../../../_base/kernel',
'dojo/has',
'dojo/has!host-browser?dojo/domReady!'
], function (registerSuite, assert, array, lang, kernel, has) {
registerSuite({
name: 'dojo/_base/lang',
'.exists': function () {
var test = {
foo: 0
};
assert.isTrue(lang.exists('foo', test), 'test.foo should exist');
assert.isFalse(lang.exists('foo.bar', test), 'test.foo.bar should not exist');
// global tests
assert.isFalse(lang.exists('_existsTest'), '_existsTest should not exist');
kernel.global._existsTest = false;
assert.isTrue(lang.exists('_existsTest'), '_existsTest should exist');
assert.isFalse(lang.exists('_existsTest.bar'), '_existsTest.bar should not exist');
// scopeMap tests
assert.isTrue(lang.exists('dojo.dijit'), 'dojo.dijit should exist');
assert.isFalse(lang.exists('dojo.foo'), 'dojo.foo should not exist');
},
'.getObject': function () {
var test = {
foo: {}
};
assert.strictEqual(lang.getObject('foo', false, test), test.foo);
assert.strictEqual(typeof lang.getObject('foo.bar', false, test), 'undefined');
assert.strictEqual(typeof lang.getObject('foo.bar', true, test), 'object');
test.foo.bar.baz = 'test';
assert.strictEqual(lang.getObject('foo.bar', false, test), test.foo.bar);
// global tests
assert.strictEqual(typeof lang.getObject('_getObjectTest.bar', false), 'undefined');
kernel.global._getObjectTest = {};
assert.strictEqual(lang.getObject('_getObjectTest', false), kernel.global._getObjectTest);
assert.strictEqual(typeof lang.getObject('_getObjectTest.bar', true), 'object');
// strangely, parser does this
assert.strictEqual(typeof lang.getObject('./TestWidget'), 'undefined');
// empty path should return the same object
assert.strictEqual(lang.getObject('', false, test), test);
assert.strictEqual(lang.getObject('', false, null), null);
assert.strictEqual(lang.getObject(''), undefined);
},
'.setObject': function () {
var test = {
foo: 0
};
lang.setObject('foo', { bar: 'test' }, test);
assert.deepEqual(test, { foo: { bar: 'test' } });
// CVE-2021-23450 tests
// Test that you can't set fields on Object.prototype itself.
const obj = {};
lang.setObject("__proto__.vuln", "polluted!", obj);
assert.isUndefined("anything".vuln);
// Test that you can't set fields on Object.constructor itself.
lang.setObject("constructor.vuln", "polluted!", obj);
assert.isUndefined("anything".constructor.vuln);
// Test that you can still set normal fields in an obj.
lang.setObject("foo.bar", "value for normal field", obj);
assert.strictEqual(obj.foo.bar, "value for normal field");
},
'.mixin': function () {
var src = {
foo: function () {
console.debug('foo');
},
bar: 'bar'
};
var dest = {};
lang.mixin(dest, src);
assert.typeOf(lang.mixin(), 'object');
assert.typeOf(lang.mixin(undefined), 'object');
assert.typeOf(lang.mixin(null), 'object');
assert.typeOf(dest.foo, 'function');
assert.typeOf(dest.bar, 'string');
},
'.extend': function () {
var src = {
foo: function () {
console.debug('foo');
},
bar: 'bar'
};
var test;
function Dest() {}
lang.extend(Dest, src);
test = new Dest();
assert.typeOf(test.foo, 'function');
assert.typeOf(test.bar, 'string');
},
'.isFunction': function () {
function test() {}
assert.isTrue(lang.isFunction(new Function()));
assert.isTrue(lang.isFunction(test));
if (has('host-browser')) { // test the Safari workaround for NodeList
assert.isFalse(lang.isFunction(document.getElementsByName('html')));
assert.isFalse(lang.isFunction(document.createElement('object')));
}
},
'.isObject': function () {
assert.isFalse(lang.isObject(true));
assert.isFalse(lang.isObject(false));
assert.isFalse(lang.isObject('foo'));
/*jshint -W053 */
assert.isTrue(lang.isObject(new String('foo')));
assert.isTrue(lang.isObject(null));
assert.isTrue(lang.isObject({}));
assert.isTrue(lang.isObject([]));
/*jshint -W009 */
assert.isTrue(lang.isObject(new Array()));
},
'.isArray': function () {
/*jshint -W009 */
assert.isTrue(lang.isArray([]));
assert.isTrue(lang.isArray(new Array()));
assert.isFalse(lang.isArray({}));
assert.isFalse(lang.isArray(''));
assert.isFalse(lang.isArray(0));
assert.isFalse(lang.isArray(NaN));
assert.isFalse(lang.isArray(null));
assert.isFalse(lang.isArray(undefined));
if (typeof window !== 'undefined') {
assert.isFalse(lang.isArray(window));
}
assert.isFalse(lang.isArray(Function));
function Tricky() {}
Tricky.prototype = [];
assert.isFalse(lang.isArray(new Tricky()));
},
'.isArrayLike': function () {
/*jshint -W009 */
assert.isFalse(lang.isArrayLike('thinger'));
assert.isTrue(lang.isArrayLike(new Array()));
assert.isFalse(lang.isArrayLike({}));
assert.isTrue(lang.isArrayLike(arguments));
assert.isFalse(lang.isArrayLike(''));
assert.isFalse(lang.isArrayLike(false));
assert.isFalse(lang.isArrayLike(NaN));
assert.isFalse(lang.isArrayLike(undefined));
assert.isFalse(lang.isArrayLike(null));
if(typeof window !== 'undefined'){
assert.isTrue(lang.isArrayLike(window));
}
assert.isFalse(lang.isArrayLike(Function));
assert.isTrue(lang.isArrayLike({0: 1, 1: 2, length: 2}));
function Tricky() {}
Tricky.prototype = [];
assert.isTrue(lang.isArrayLike(new Tricky()));
},
'.isString': function () {
/*jshint -W053 */
assert.isFalse(lang.isString(true));
assert.isFalse(lang.isString(false));
assert.isTrue(lang.isString('foo'));
assert.isTrue(lang.isString(new String('foo')));
assert.isFalse(lang.isString(null));
assert.isFalse(lang.isString({}));
assert.isFalse(lang.isString([]));
},
'.partial': function () {
var scope = { foo: 'bar' };
var st1;
var st2;
var st3;
function thinger(arg1, arg2) {
return [this.foo, arg1, arg2];
}
st1 = lang.partial(thinger);
assert.equal('bar', st1.call(scope)[0]);
assert.equal(undefined, st1()[0]);
st2 = lang.partial(thinger, 'foo', 'bar');
assert.equal('bar', st2()[2]);
st3 = lang.partial(thinger, 'foo', 'bar');
},
'.partial nested': function () {
var st1;
var st2;
function thinger(arg1, arg2) {
return [arg1, arg2];
}
st1 = lang.partial(thinger, 'foo');
assert.equal(undefined, st1()[1]);
assert.equal('bar', st1('bar')[1]);
// partials can accumulate
st2 = lang.partial(st1, 'thud');
assert.equal('foo', st2()[0]);
assert.equal('thud', st2()[1]);
},
'.hitch': function () {
var scope = { foo: 'bar' };
var scope2 = { foo: 'baz' };
var st1;
var st2;
function thinger() {
return [this.foo, arguments.length];
}
st1 = lang.hitch(scope, thinger);
assert.equal('bar', st1()[0]);
assert.equal(0, st1()[1]);
st2 = lang.hitch(scope2, thinger);
assert.equal('baz', st2()[0]);
assert.equal(0, st1()[1]);
assert.equal(1, st1('blah')[1]);
// st2 should be "scope proof"
assert.equal('baz', st2.call(scope)[0]);
},
'.hitch with args': function () {
var scope = { foo: 'bar' };
var scope2 = { foo: 'baz' };
var st1;
var st2;
function thinger() {
return [this.foo, arguments.length];
}
st1 = lang.hitch(scope, thinger, 'foo', 'bar');
assert.equal('bar', st1()[0]);
assert.equal(2, st1()[1]);
st2 = lang.hitch(scope2, thinger, 'foo', 'bar');
assert.equal('baz', st2()[0]);
assert.equal(2, st2()[1]);
},
'.hitch as partial': function () {
var scope = { foo: 'bar' };
var st1;
var st2;
function thinger(arg1, arg2) {
return [this.foo, arg1, arg2];
}
st1 = lang.hitch(null, thinger);
assert.equal('bar', st1.call(scope)[0]);
assert.equal(undefined, st1()[0]);
st2 = lang.hitch(null, thinger, 'foo', 'bar');
assert.equal('bar', st2()[2]);
},
'.toArray': function () {
var obj1 = [ 'foo', 'bar', 'spam', 'ham' ];
var obj2;
var div;
var result;
function thinger() {
return lang._toArray(arguments);
}
obj2 = thinger.apply(this, obj1);
assert.equal(obj1[0], obj2[0]);
if (has('host-browser')) {
// test DomCollection
div = document.createElement('div');
div.innerHTML = '<a href="#"">link</a>text';
result = lang._toArray(div.childNodes);
assert.equal(2, result.length);
}
},
'.clone': function () {
var obj1 = {
foo: 'bar',
answer: 42,
jan102007: new Date(2007, 0, 10),
baz: {
a: null,
b: [1, 'b', 2.3, true, false],
c: {
d: undefined,
e: 99,
f: function () { console.log(42); return 42; },
g: /\d+/gm
}
},
toString: function () { return 'meow'; }
};
assert.deepEqual(obj1, lang.clone(obj1));
obj1.baz.b[6] = "c"; // intentional sparse populatation
assert.deepEqual(obj1.baz.b, lang.clone(obj1).baz.b, "Sparse arrays should be equal");
},
'.delegate': function () {
var a = {
x: 1,
y: function () { return 2; },
z1: 99
};
var b = {
x: 11,
y: function () { return 12; },
z2: 33,
toString: function () { return 'bark!'; },
toLocaleString: function () { return 'le bark-s!'; }
};
var c;
assert.strictEqual(1, a.x);
assert.strictEqual(2, a.y());
assert.strictEqual(99, a.z1);
c = lang.delegate(a, b);
assert.strictEqual(1, a.x);
assert.strictEqual(2, a.y());
assert.strictEqual(99, a.z1);
assert.strictEqual(11, c.x);
assert.strictEqual(12, c.y());
assert.strictEqual('bark!', c.toString());
assert.strictEqual('le bark-s!', c.toLocaleString());
assert.strictEqual(99, c.z1);
assert.strictEqual(33, c.z2);
},
'.replace with object': function () {
var objectContext = {
nick: 'Bob',
name: {
first: 'Robert',
middle: 'X',
last: 'Cringely'
}
};
var s1 = lang.replace('Hello, {name.first} {name.last} AKA {nick}!', objectContext);
assert.equal('Hello, Robert Cringely AKA Bob!', s1);
},
'.replace with array context': function () {
var arrayContext = ['Robert', 'X', 'Cringely'];
var s2 = lang.replace('Hello, {0} {2}!', arrayContext);
assert.equal('Hello, Robert Cringely!', s2);
},
'.replace with function': function () {
function sum(a) {
var t = 0;
array.forEach(a, function (x) { t += x; });
return t;
}
var s1 = lang.replace(
'{count} payments averaging {avg} USD per payment.',
lang.hitch(
{ payments: [11, 16, 12] },
function (_, key) {
switch (key) {
case 'count':
return this.payments.length;
case 'avg':
return sum(this.payments) / this.payments.length;
}
return '';
}
));
assert.equal('3 payments averaging 13 USD per payment.', s1);
},
'.replace with regex': function () {
var s4 = lang.replace('Hello, ${0} ${2}!', ['Robert', 'X', 'Cringely'], /\$\{([^\}]+)\}/g);
assert.equal('Hello, Robert Cringely!', s4);
}
});
});