mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
263 lines
9.7 KiB
JavaScript
263 lines
9.7 KiB
JavaScript
|
var assert = require('chai').assert;
|
||
|
var gutil = require('app/common/gutil');
|
||
|
var _ = require('underscore');
|
||
|
|
||
|
describe('gutil', function() {
|
||
|
|
||
|
describe("mapToObject", function() {
|
||
|
it("should produce an object with all keys", function() {
|
||
|
assert.deepEqual(gutil.mapToObject(["foo", "bar", "baz"], function(value, i) {
|
||
|
return [value.toUpperCase(), i];
|
||
|
}), {
|
||
|
"foo": ["FOO", 0],
|
||
|
"bar": ["BAR", 1],
|
||
|
"baz": ["BAZ", 2]
|
||
|
});
|
||
|
|
||
|
assert.deepEqual(gutil.mapToObject(["foo", "bar", "baz"], function() {}), {
|
||
|
"foo": undefined,
|
||
|
"bar": undefined,
|
||
|
"baz": undefined,
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it("should work on an empty array", function() {
|
||
|
var countCalls = 0;
|
||
|
assert.deepEqual(gutil.mapToObject([], function() { countCalls++; }), {});
|
||
|
assert.equal(countCalls, 0);
|
||
|
});
|
||
|
|
||
|
it("should override values for duplicate keys", function() {
|
||
|
assert.deepEqual(gutil.mapToObject(["foo", "bar", "foo"], function(val, i) { return i; }),
|
||
|
{ "foo": 2, "bar": 1 });
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('multiCompareFunc', function() {
|
||
|
var firstName = {
|
||
|
0: 'John',
|
||
|
1: 'John',
|
||
|
2: 'John',
|
||
|
3: 'John',
|
||
|
4: 'Johnson',
|
||
|
5: 'Johnson',
|
||
|
};
|
||
|
var lastName = {
|
||
|
0: 'Smith',
|
||
|
1: 'Smith',
|
||
|
2: 'Smith',
|
||
|
3: 'Smithy',
|
||
|
4: 'Smithy',
|
||
|
5: 'Smith',
|
||
|
};
|
||
|
var age = {
|
||
|
0: 20,
|
||
|
1: 30,
|
||
|
2: 21,
|
||
|
3: 31,
|
||
|
4: 40,
|
||
|
5: 50,
|
||
|
};
|
||
|
|
||
|
it('should do single comparisons', function() {
|
||
|
var sort1 = [_.propertyOf(firstName)];
|
||
|
var compareA = gutil.multiCompareFunc(sort1, [gutil.nativeCompare], [1]);
|
||
|
var compareD = gutil.multiCompareFunc(sort1, [gutil.nativeCompare], [-1]);
|
||
|
assert.equal(compareA(0, 1), 0); // John == John
|
||
|
assert.equal(compareD(0, 1), 0);
|
||
|
assert.isBelow(compareA(0, 4), 0); // John < Johnson if ascending
|
||
|
assert.isAbove(compareA(4, 0), 0);
|
||
|
assert.isAbove(compareD(0, 4), 0); // John > Johnson if descending
|
||
|
assert.isBelow(compareD(4, 0), 0);
|
||
|
});
|
||
|
|
||
|
it('should do multiple comparisons', function() {
|
||
|
var sort2 = [_.propertyOf(firstName), _.propertyOf(lastName)];
|
||
|
var sort3 = [_.propertyOf(firstName), _.propertyOf(lastName), _.propertyOf(age)];
|
||
|
var compare2 = gutil.multiCompareFunc(sort2, [gutil.nativeCompare, gutil.nativeCompare], [1, 1]);
|
||
|
var compare3 = gutil.multiCompareFunc(sort3,
|
||
|
[gutil.nativeCompare, gutil.nativeCompare, gutil.nativeCompare], [1, 1, -1]);
|
||
|
|
||
|
assert.equal(compare2(0, 1), 0); // John Smith, 20 = John Smith, 30
|
||
|
assert.equal(compare2(1, 2), 0); // John Smith, 30 = John Smith, 21
|
||
|
assert.isBelow(compare2(0, 3), 0); // John Smith < John Smithy
|
||
|
assert.isBelow(compare2(0, 4), 0); // John Smith < Johnson Smithy
|
||
|
assert.isBelow(compare2(0, 5), 0); // John Smith < Johnson Smith
|
||
|
|
||
|
assert.isAbove(compare3(0, 1), 0); // John Smith, 20 > John Smith, 30 (age descending)
|
||
|
assert.isBelow(compare3(1, 2), 0); // John Smith, 30 < John Smith, 21
|
||
|
assert.isBelow(compare3(0, 3), 0); // John Smith, 20 < John Smithy, 31
|
||
|
assert.isBelow(compare3(0, 4), 0); // John Smith, 20 < Johnson Smithy, 40
|
||
|
assert.isBelow(compare3(3, 4), 0); // John Smithy, 20 < Johnson Smithy, 40
|
||
|
assert.isAbove(compare3(4, 5), 0); // Johnson Smithy > Johnson Smith
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("deepExtend", function() {
|
||
|
var sample = {
|
||
|
a: 1,
|
||
|
b: "hello",
|
||
|
c: [1, 2, 3],
|
||
|
d: { e: 1, f: 2 }
|
||
|
};
|
||
|
it("should copy recursively", function() {
|
||
|
assert.deepEqual(gutil.deepExtend({}, {}), {});
|
||
|
assert.deepEqual(gutil.deepExtend({}, sample), sample);
|
||
|
assert.deepEqual(gutil.deepExtend({}, sample, {}), sample);
|
||
|
assert.deepEqual(gutil.deepExtend({}, sample, sample), sample);
|
||
|
assert.deepEqual(gutil.deepExtend({}, sample, {a: 2}).a, 2);
|
||
|
assert.deepEqual(gutil.deepExtend({}, sample, {d: {g: 3}}).d, {e:1, f:2, g:3});
|
||
|
assert.deepEqual(gutil.deepExtend({c: [4, 5, 6, 7], d: {g: 3}}, sample).d, {e:1, f:2, g:3});
|
||
|
assert.deepEqual(gutil.deepExtend({c: [4, 5, 6, 7], d: {g: 3}}, sample).c, [1, 2, 3, 7]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("maxsplit", function() {
|
||
|
it("should respect maxNumSplits parameter", function() {
|
||
|
assert.deepEqual(gutil.maxsplit("foo bar baz", " ", 0), ["foo bar baz"]);
|
||
|
assert.deepEqual(gutil.maxsplit("foo bar baz", " ", 1), ["foo", "bar baz"]);
|
||
|
assert.deepEqual(gutil.maxsplit("foo bar baz", " ", 2), ["foo", "bar", "baz"]);
|
||
|
assert.deepEqual(gutil.maxsplit("foo bar baz", " ", 3), ["foo", "bar", "baz"]);
|
||
|
assert.deepEqual(gutil.maxsplit("foo<x>bar<x>baz", "<x>", 1), ["foo", "bar<x>baz"]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("arrayInsertBefore", function() {
|
||
|
it("should insert before the given nextValue", function() {
|
||
|
var array = ["foo", "bar", "baz"];
|
||
|
gutil.arrayInsertBefore(array, "asdf", "foo");
|
||
|
assert.deepEqual(array, ["asdf", "foo", "bar", "baz"]);
|
||
|
gutil.arrayInsertBefore(array, "hello", "baz");
|
||
|
assert.deepEqual(array, ["asdf", "foo", "bar", "hello", "baz"]);
|
||
|
gutil.arrayInsertBefore(array, "zoo", "unknown");
|
||
|
assert.deepEqual(array, ["asdf", "foo", "bar", "hello", "baz", "zoo"]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("popFromMap", function() {
|
||
|
it("should return the value for the popped key", function() {
|
||
|
var map = new Map([["foo", 1], ["bar", 2], ["baz", 3]]);
|
||
|
assert.equal(gutil.popFromMap(map, "bar"), 2);
|
||
|
assert.deepEqual(Array.from(map), [["foo", 1], ["baz", 3]]);
|
||
|
assert.strictEqual(gutil.popFromMap(map, "unknown"), undefined);
|
||
|
assert.deepEqual(Array.from(map), [["foo", 1], ["baz", 3]]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("isSubset", function() {
|
||
|
it("should determine the subset relationship for Sets", function() {
|
||
|
let sEmpty = new Set(),
|
||
|
sFoo = new Set([1]),
|
||
|
sBar = new Set([2, 3]),
|
||
|
sBaz = new Set([1, 2, 3]);
|
||
|
|
||
|
assert.isTrue(gutil.isSubset(sEmpty, sFoo));
|
||
|
assert.isFalse(gutil.isSubset(sFoo, sEmpty));
|
||
|
|
||
|
assert.isTrue(gutil.isSubset(sFoo, sBaz));
|
||
|
assert.isFalse(gutil.isSubset(sFoo, sBar));
|
||
|
|
||
|
assert.isTrue(gutil.isSubset(sBar, sBaz));
|
||
|
assert.isTrue(gutil.isSubset(sBar, sBar));
|
||
|
|
||
|
assert.isTrue(gutil.isSubset(sBaz, sBaz));
|
||
|
assert.isFalse(gutil.isSubset(sBaz, sBar));
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("growMatrix", function() {
|
||
|
it("should grow the matrix to the desired size", function() {
|
||
|
let matrix = [["a", 1], ["b", 2], ["c", 3]];
|
||
|
assert.deepEqual(gutil.growMatrix(matrix, 4, 4),
|
||
|
[["a", 1, "a", 1],
|
||
|
["b", 2, "b", 2],
|
||
|
["c", 3, "c", 3],
|
||
|
["a", 1, "a", 1]]);
|
||
|
assert.deepEqual(gutil.growMatrix(matrix, 3, 4),
|
||
|
[["a", 1, "a", 1],
|
||
|
["b", 2, "b", 2],
|
||
|
["c", 3, "c", 3]]);
|
||
|
assert.deepEqual(gutil.growMatrix(matrix, 6, 2),
|
||
|
[["a", 1],
|
||
|
["b", 2],
|
||
|
["c", 3],
|
||
|
["a", 1],
|
||
|
["b", 2],
|
||
|
["c", 3]]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("sortedScan", function() {
|
||
|
it("should callback on the correct items for simple arrays", function() {
|
||
|
const a = [1, 2, 4, 5, 7, 8, 9, 10, 11, 15, 17];
|
||
|
const b = [2, 3, 4, 5, 9, 11, 19];
|
||
|
|
||
|
// Run the scan function, allowing it to populate callArgs.
|
||
|
let callArgs = [];
|
||
|
gutil.sortedScan(a, b, (ai, bi) => { callArgs.push([ai, bi]); });
|
||
|
|
||
|
assert.deepEqual(callArgs,
|
||
|
[[1, null], [2, 2], [null, 3], [4, 4],
|
||
|
[5, 5], [7, null], [8, null], [9, 9],
|
||
|
[10, null], [11, 11], [15, null], [17, null],
|
||
|
[null, 19]]);
|
||
|
});
|
||
|
|
||
|
it("should callback on the correct items for object arrays", function() {
|
||
|
const a = [{ id: 1, fruit: 'apple' },
|
||
|
{ id: 2, fruit: 'banana' },
|
||
|
{ id: 4, fruit: 'orange' },
|
||
|
{ id: 5, fruit: 'peach' },
|
||
|
{ id: 6, fruit: 'plum' }];
|
||
|
const b = [{ id: 2, fruit: 'apple' },
|
||
|
{ id: 3, fruit: 'avocado' },
|
||
|
{ id: 4, fruit: 'peach' },
|
||
|
{ id: 6, fruit: 'pear' },
|
||
|
{ id: 9, fruit: 'plum' },
|
||
|
{ id: 10, fruit: 'raspberry' }];
|
||
|
|
||
|
// Run the scan function.
|
||
|
let fruitArgs = [];
|
||
|
gutil.sortedScan(a, b, (ai, bi) => {
|
||
|
fruitArgs.push([ai ? ai.fruit : '', bi ? bi.fruit : '']);
|
||
|
}, item => item.id);
|
||
|
|
||
|
assert.deepEqual(fruitArgs,
|
||
|
[['apple', ''], ['banana', 'apple'], ['', 'avocado'],
|
||
|
['orange', 'peach'], ['peach', ''], ['plum', 'pear'],
|
||
|
['', 'plum'], ['', 'raspberry']]);
|
||
|
|
||
|
// Run the scan function again, using fruit as the key.
|
||
|
let idArgs = [];
|
||
|
gutil.sortedScan(a, b, (ai, bi) => {
|
||
|
idArgs.push([ai ? ai.id : 0, bi ? bi.id : 0]);
|
||
|
}, item => item.fruit);
|
||
|
|
||
|
assert.deepEqual(idArgs,
|
||
|
[[1, 2], [0, 3], [2, 0], [4, 0],
|
||
|
[5, 4], [0, 6], [6, 9], [0, 10]]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe("isEmail", function() {
|
||
|
it("should distinguish valid and invalid emails", function() {
|
||
|
// Reference: https://blogs.msdn.microsoft.com/testing123/2009/02/06/email-address-test-cases/
|
||
|
assert.isTrue(gutil.isEmail('email@domain.com'));
|
||
|
assert.isTrue(gutil.isEmail('e-mail_123@domain.com'));
|
||
|
assert.isTrue(gutil.isEmail('email@subdomain.do-main.com'));
|
||
|
assert.isTrue(gutil.isEmail('firstname+lastname@domain.com'));
|
||
|
assert.isTrue(gutil.isEmail('email@domain.co.jp'));
|
||
|
|
||
|
assert.isFalse(gutil.isEmail('plainaddress'));
|
||
|
assert.isFalse(gutil.isEmail('@domain.com'));
|
||
|
assert.isFalse(gutil.isEmail('email@domain@domain.com'));
|
||
|
assert.isFalse(gutil.isEmail('.email@domain.com'));
|
||
|
assert.isFalse(gutil.isEmail('email.@domain.com'));
|
||
|
assert.isFalse(gutil.isEmail('email..email@domain.com'));
|
||
|
assert.isFalse(gutil.isEmail('あいうえお@domain.com'));
|
||
|
assert.isFalse(gutil.isEmail('email@domain'));
|
||
|
});
|
||
|
});
|
||
|
|
||
|
});
|