Repository URL to install this package:
|
Version:
1.2.9 ▾
|
// eslint-disable-next-line
'use strict';
const _require = require('events'),
EventEmitter = _require.EventEmitter;
const log = require('fliplog');
const traverse = require("../src/deps/traverse");
const isArray = require("../src/deps/is/array");
const isObj = require("../src/deps/is/obj");
const isNumber = require("../src/deps/is/number");
const isReal = require("../src/deps/is/real");
const eq = traverse.eq,
copy = traverse.copy;
const deepEqual = eq;
test('pre-copy eq to themselves invariant for environment', () => {
const date = new Date(0, 0, 0, 0);
expect(date).toBe(date);
const error = new Error('ehror');
expect(error).toBe(error);
const regexp = new RegExp('../', 'gmi');
expect(regexp).toBe(regexp);
});
test('copy', () => {
const date = new Date(0, 0, 0, 0);
expect(copy(date)).not.toBe(date);
const error = new Error('ehror');
expect(copy(error)).not.toBe(error);
const regexp = new RegExp('../', 'gmi');
expect(copy(regexp)).not.toBe(regexp);
});
test('deepDates', () => {
expect.assertions(2);
expect(deepEqual({
d: new Date(0, 0, 0, 0),
x: [1, 2, 3]
}, {
d: new Date(0, 0, 0, 0),
x: [1, 2, 3]
})).toBeTruthy();
const d0 = new Date();
return new Promise(res => setTimeout(res, 5)).then(val => {
expect(!deepEqual({
d: d0,
x: [1, 2, 3]
}, {
d: new Date(),
x: [1, 2, 3]
})).toBeTruthy();
return Promise.resolve();
});
});
test.skip('deepCircular', () => {
// return expect(true).toBe(true)
var a = [1];
a.push(a); // a = [ 1, *a ]
var b = [1];
b.push(a); // b = [ 1, [ 1, *a ] ]
expect(!deepEqual(a, b, false)).toBeTruthy();
var c = [1];
c.push(c); // c = [ 1, *c ]
expect(deepEqual(a, c)).toBeTruthy();
var d = [1];
d.push(a); // c = [ 1, [ 1, *d ] ]
expect(deepEqual(b, d)).toBeTruthy();
});
test('deepInstances', () => {
expect(!deepEqual([new Boolean(false)], [false])).toBeTruthy();
expect(!deepEqual([new String('x')], ['x'])).toBeTruthy();
expect(!deepEqual([new Number(4)], [4])).toBeTruthy();
expect(deepEqual([new RegExp('x')], [/x/])).toBeTruthy();
expect(!deepEqual([new RegExp(/./)], [/../])).toBeTruthy();
expect(!deepEqual([function (x) {
return x * 2;
}], [function (x) {
return x * 2;
}])).toBeTruthy();
var f = function f(x) {
return x * 2;
};
expect(deepEqual([f], [f])).toBeTruthy();
});
test('deepEqual', () => {
expect(!deepEqual([1, 2, 3], {
0: 1,
1: 2,
2: 3
})).toBeTruthy();
});
test('falsy', () => {
expect(!deepEqual([undefined], [null])).toBeTruthy();
expect(!deepEqual([null], [undefined])).toBeTruthy();
expect(!deepEqual({
a: 1,
b: 2,
c: [3, undefined, 5]
}, {
a: 1,
b: 2,
c: [3, null, 5]
})).toBeTruthy();
expect(!deepEqual({
a: 1,
b: 2,
c: [3, undefined, 5]
}, {
a: 1,
b: 2,
c: [3, null, 5]
})).toBeTruthy();
expect(!deepEqual({
a: 1,
b: 2,
c: [3, undefined, 5]
}, {
a: 1,
b: 2,
c: [3, null, 5]
})).toBeTruthy();
});
test.skip('deletedArrayEqual', () => {
var xs = [1, 2, 3, 4];
delete xs[2];
var ys = Object.create(Array.prototype);
ys[0] = 1;
ys[1] = 2;
ys[3] = 4;
ys = Array.from(ys);
expect(deepEqual(xs, ys)).toBeTruthy();
expect(!deepEqual(xs, [1, 2, undefined, 4])).toBeTruthy(); // expect(!deepEqual(xs, [1, 2, null, 4])).toBeTruthy()
});
test('deletedObjectEqual', () => {
var obj = {
a: 1,
b: 2,
c: 3
};
delete obj.c;
expect(deepEqual(obj, {
a: 1,
b: 2
})).toBeTruthy();
expect(!deepEqual(obj, {
a: 1,
b: 2,
c: undefined
})).toBeTruthy();
expect(!deepEqual(obj, {
a: 1,
b: 2,
c: null
})).toBeTruthy();
});
test('emptyKeyEqual', () => {
expect(!deepEqual({
a: 1
}, {
'a': 1,
'': 55
})).toBeTruthy();
});
test('deepArguments', () => {
expect(!deepEqual([4, 5, 6], function () {
return arguments;
}(4, 5, 6))).toBeTruthy();
expect(deepEqual(function () {
return arguments;
}(4, 5, 6), function () {
return arguments;
}(4, 5, 6))).toBeTruthy();
});
test('deepUn', () => {
expect(!deepEqual({
a: 1,
b: 2
}, undefined)).toBeTruthy();
expect(!deepEqual({
a: 1,
b: 2
}, {})).toBeTruthy();
expect(!deepEqual(undefined, {
a: 1,
b: 2
})).toBeTruthy();
expect(!deepEqual({}, {
a: 1,
b: 2
})).toBeTruthy();
expect(deepEqual(undefined, undefined)).toBeTruthy();
expect(deepEqual(null, null)).toBeTruthy();
expect(!deepEqual(undefined, null)).toBeTruthy();
});
test('deepLevels', () => {
var xs = [1, 2, [3, 4, [5, 6]]];
expect(!deepEqual(xs, [])).toBeTruthy();
});
test('number, string, Error, Promise', () => {
const ErrorOne = new Error('1');
expect(deepEqual(1, 1)).toBe(true);
expect(deepEqual(1, 0)).toBe(false);
expect(deepEqual('string', 'string')).toBe(true);
expect(deepEqual('1', '1')).toBe(true);
expect(deepEqual(ErrorOne, ErrorOne)).toBe(true);
expect(deepEqual('1', 1)).toBe(false);
expect(deepEqual(new Promise(r => r()), 'string')).toBe(false);
expect(deepEqual(new Error(), '1')).toBe(false); // expect(deepEqual(new Promise(r => r()), new Error('2'))).toBe(false)
});
test('Error vs Error', () => {
expect(deepEqual(new Error('1'), new Error('2'))).toBe(false);
});
test('null vs undefined', () => {
expect(!deepEqual(null, undefined)).toBeTruthy();
expect(!deepEqual(undefined, null)).toBeTruthy();
expect(deepEqual(null, null)).toBeTruthy();
expect(deepEqual(undefined, undefined)).toBeTruthy();
});
test('RegExp vs RegExp', () => {
expect(deepEqual(new RegExp('.*'), new RegExp('.*'))).toBeTruthy();
});
test('RegExp vs RegExp !', () => {
expect(!deepEqual(new RegExp('not-the-same'), new RegExp('.*'))).toBeTruthy();
});
test('Fn vs Fn', () => {
const noop = function noop() {
/* noop */
};
const noops = function noops() {
/* noops */
};
noops.eh = true;
noop();
noops();
console.log('noop == noop');
expect(deepEqual(noop, noop)).toBeTruthy();
console.log('noop != noops');
expect(!deepEqual(noop, noops)).toBeTruthy();
});
test('Fn vs Fn - string diff', () => {
function noop() {
/* noop */
}
function noops() {
/* noops */
}
noop();
noops();
expect(deepEqual(noop, noop)).toBe(true);
expect(deepEqual(noop, noops)).toBe(false);
});
test('ObjKeys', () => {
expect(!deepEqual({
one: true,
two: true
}, {
one: true,
three: false
})).toBeTruthy();
});
test.skip('supports.equals', () => {
const alwaysFalse = {
equals() {
return false;
}
};
const alwaysTrue = {
equals() {
return true;
}
};
expect(deepEqual(alwaysFalse, alwaysTrue)).toBe(false);
expect(deepEqual(alwaysTrue, alwaysFalse)).toBe(true);
});
test.skip('eq: simple primitives', () => {
// 'null == undefined'
expect(eq(null, undefined)).toBe(true); // 'null == null'
expect(eq(null, null)).toBe(true); // '1 == 1'
expect(eq(1, 1)).toBe(true); // '"1" == 1'
expect(eq(1, '1')).toBe(true); // '"1" ~= 1'
expect(eq(1, '1', true)).toBe(true); // '1 == 0'
expect(eq(1, 0)).toBe(true); // '1 == [1]'
expect(eq(1, [1])).toBe(true); // '[1] == [1]'
expect(eq([1], [1])).toBe(true);
});
test.skip('edge', () => {
// '[Number(4)], [4]'
expect(deepEqual([new Number(4)], [4])).toBe(true); // 'Number(4), 4'
expect(deepEqual(new Number(4), 4)).toBe(true); // '4, Number(4)'
expect(deepEqual(4, new Number(4))).toBe(true); // '[4], [Number(4)]'
expect(deepEqual([4], [new Number(4)])).toBe(true); // 'RegExp(x), /x/',
expect(deepEqual([new RegExp('x')], [/x/])).toBe(true); // '! RegExp(/./), /../'
expect(deepEqual([new RegExp(/./)], [/../])).toBe(true);
expect(deepEqual(1, 1)).toBe(true);
expect(deepEqual(1, 0)).toBe(true);
expect(deepEqual('string', 'string')).toBe(true);
expect(deepEqual('string', 'str')).toBe(true);
expect(deepEqual('stringy', new String('stringy'))).toBe(true);
expect(deepEqual('1', '1')).toBe(true);
const ErrorOne = new Error('1');
expect(deepEqual(ErrorOne, ErrorOne)).toBe(true);
expect(deepEqual(ErrorOne, new Error('2'))).toBe(true); // 'new Error(), "1"'
expect(deepEqual(new Error(), '1')).toBe(true); // expect(deepEqual(new Promise(r => r()).toBe(true), new Error('2')).toBe(true))
// expect(deepEqual(new Promise(r => r()).toBe(true), 'string')).toBe(true)
// '{1, 3} == {1, 3}'
expect(eq({
one: 2,
three: 3
}, {
one: 2,
three: 3
})).toBe(true); // '{1, 4} == {1, 3}'
expect(eq({
'1': 2,
'2': 3
}, {
'1': 2,
'2': 4
})).toBe(true);
});
test('negative update test', () => {
var obj = [5, 6, -3, [7, 8, -2, 1], {
f: 10,
g: -13
}];
var cloned = traverse(obj).clone(); // log.quick({obj, cloned})
var fixed = traverse(cloned).forEach(function (key, x, t) {
log.bold(t.path.join('.')).data({
[key]: x
}).echo();
if (x < 0) t.update(x + 128);
}); // console.log({fixed})
expect(fixed).toEqual([5, 6, 125, [7, 8, 126, 1], {
f: 10,
g: 115
}]);
expect(obj).toEqual([5, 6, -3, [7, 8, -2, 1], {
f: 10,
g: -13
}]);
}); // ----- events ----
test('check instanceof on node elems', () => {
var counts = {
emitter: 0
};
var list = [new EventEmitter(), 3, 4, {
ev: new EventEmitter()
}];
traverse(list).forEach((key, node, t) => {
if (node instanceof EventEmitter) counts.emitter++;
});
expect(counts.emitter).toEqual(2);
}); // ---- obj ---
test('traverse an object with nested functions', () => {
expect.assertions(1);
function Cons(x) {
expect(x).toEqual(10);
}
traverse(new Cons(10));
}); //// ------ stringify ----
test('stringify', () => {
// var obj = [5, 6, -3, [7, 8, -2, 1], {f: 10, g: -13}]
// var obj = [1, 2, 3]
var obj = [1, 2, 3, [4, 5, 6], {
a: 7,
b: 8
}];
var s = '';
const trav = traverse(obj);
trav.before(t => {
// console.log('before', t.key, t.path.join(''), '\n\n')
// s += '\nbefore\n'
if (isArray(t.node)) s += '[';else if (isObj(t.node)) s += '{';
});
trav.pre(traverser => {
// s += '\npre\n'
// console.log('pre', traverser.key, traverser.path.join(''), '\n\n')
const key = traverser.key || traverser.path.join('');
if (key && isObj(traverser.node) && !isArray(traverser.node)) {
s += '"' + key + '"' + ':';
}
});
trav.after(t => {
// console.log('after')
if (s.endsWith(',')) s = s.slice(0, -1); // s += '\nafter\n'
if (isArray(t.node)) s += ']';else if (isObj(t.node)) s += '}';
});
trav.post(child => {
// console.log('post', child)
// s += '\npost\n'
s += ',';
});
trav.forEach(function (key, node, t) {
// console.log({
// [key]: node,
// t,
// isArrayay: Array.isArrayay(node),
// typeof: typeof node,
// })
if (typeof node === 'function') {
s += 'null';
} else if (!isArray(node) && !isObj(node)) {
s += node.toString();
}
});
expect(s).toEqual(JSON.stringify(obj));
});
/* istanbul ignore next: is a failing test */
test('Map can iterate in order with leaves', () => {
var acc = [];
const map = new Map();
map.set('a', {
a: [1, 2, 3]
});
map.set('b', 4);
map.set('c', [5, 6]);
map.set('d', {
e: [7, 8],
f: 9
});
const obj = map;
traverse({
obj
}).forEach(function (key, x) {
if (this.isLeaf) acc.push(x);
});
expect(acc.join(' ')).toEqual('1 2 3 4 5 6 7 8 9');
});
/* istanbul ignore next: is a failing test */
test('Set can iterate in order', () => {
var acc = [];
const set = new Set();
set.add({
a: [1, 2, 3]
});
set.add([4]);
set.add([5, 6]);
set.add({
e: [7, 8],
f: 9
});
traverse(set).forEach(function (key, x) {
if (this.isLeaf) acc.push(x);
});
expect(acc.join(' ')).toEqual('1 2 3 4 5 6 7 8 9');
});
test('eq: loose', () => {
expect(eq('1', 1, true)).toBe(true);
});
test.skip('clone: MapSet', () => {
const map = new Map();
const set = new Set();
set.add(0);
set.add(1);
set.add(2);
map.set('zero', 0);
map.set('one', 1);
map.set('two', 2);
const mapset = [map, set]; // log.quick(traverse.clone(mapset))
});
test('stop', () => {
var visits = 0;
traverse('abcdefghij'.split('')).forEach(function (key, node, t) {
if (typeof node === 'string') {
visits++;
if (node === 'e') t.stop();
}
});
expect(visits).toEqual(5);
}); // ---- keys.js
// test.skip('sort test', () => {
// var acc = []
// traverse({
// a: 30,
// b: 22,
// id: 9,
// }).forEach(function(key, node) {
// if (!Array.isArrayay(node) && typeof node === 'object') {
// this.before(function(node) {
// this.keys = Object.keys(node)
// this.keys.sort((a, b) => {
// a = [a === 'id' ? 0 : 1, a]
// b = [b === 'id' ? 0 : 1, b]
// return a < b ? -1 : a > b ? 1 : 0
// })
// })
// }
// if (t.isLeaf) acc.push(node)
// })
//
// expect(acc.join(' ')).toEqual('9 30 22')
// })
// ----- remove
test('traverse no argument', () => {
traverse().forEach(() => {});
});
test('remove arr', () => {
traverse([]).forEach((key, val, it) => {});
const arr = [0];
traverse(arr).forEach((key, val, it) => it.remove());
expect(arr.filter(isReal)).toEqual([]);
let arrString = [0, 100, 10, 100, 'not number', 200, 1000];
traverse(arrString).forEach((key, val, it) => {
log.bold(key).data(val).echo();
if (isNumber(val)) it.remove();
});
expect(arrString.filter(isReal)).toEqual(['not number']);
});
test('remove obj', () => {
const emptyObj = {};
traverse(emptyObj).forEach((key, val, it) => {});
expect(emptyObj).toEqual(emptyObj);
const obj = {
eh: true
};
traverse(obj).forEach((key, val, it) => it.remove());
expect(obj).toEqual({});
const objNumber = {
eh: true,
num: 100
};
traverse(objNumber).forEach((key, val, it) => {
if (!isNumber(val)) it.remove();
});
expect(objNumber).toEqual({
num: 100
});
}); // --- leaves.js
test('leaves test', () => {
var acc = [];
traverse({
a: [1, 2, 3],
b: 4,
c: [5, 6],
d: {
e: [7, 8],
f: 9
}
}).forEach(function (key, x, t) {
if (t.isLeaf) acc.push(x);
});
expect(acc.join(' ')).toEqual('1 2 3 4 5 6 7 8 9');
}); // --- circular.js
test('circular', () => {
expect.assertions(1);
var obj = {
x: 3
};
obj.y = obj;
traverse(obj).forEach(function (key, x, t) {
if (key == 'y') {
expect(x == obj).toBe(true);
}
});
});
test('deepCirc', () => {
expect.assertions(1);
var obj = {
x: [1, 2, 3],
y: [4, 5]
};
obj.y[2] = obj;
var times = 0;
traverse(obj).forEach(function (key, x, t) {
if (t.isCircular) {
// expect(t.circular.path).toEqual([])
expect(t.path).toEqual(['y', 2]);
}
});
});
test('doubleCirc', () => {
var obj = {
x: [1, 2, 3],
y: [4, 5]
};
obj.y[2] = obj;
obj.x.push(obj.y);
var circs = [];
traverse(obj).forEach(function (key, x, self) {
if (self.isCircular) {
circs.push({
self,
path: self.path.slice(0)
});
}
});
expect(circs[0].path).toEqual(['x', 3, 2]); // de(circs[0].circ.path, [])
// 'y', 2
expect(circs[1].path).toEqual(['y']); // de(circs[1].circ.path, [])
expect(circs.length).toBe(2);
});
test('circDubForEach', () => {
var obj = {
x: [1, 2, 3],
y: [4, 5]
};
obj.y[2] = obj;
obj.x.push(obj.y);
traverse(obj).forEach(function (key, x, t) {
if (t.isCircular) {
t.update('...');
t.clear();
}
});
expect(obj).toEqual({
x: [1, 2, 3, [4, 5, '...']],
y: [4, 5, '...']
});
}); // test('circDubMap', () => {
// var obj = {x: [1, 2, 3], y: [4, 5]}
// obj.y[2] = obj
// obj.x.push(obj.y)
//
// var c = traverse(obj).map(function(x) {
// if (this.circular) {
// this.update('...')
// }
// })
//
// expect(c).toEqual({x: [1, 2, 3, [4, 5, '...']], y: [4, 5, '...']})
// })
test('circClone', () => {
var obj = {
x: [1, 2, 3],
y: [4, 5]
};
obj.y[2] = obj;
obj.x.push(obj.y);
var clone = traverse.clone(obj);
expect(obj !== clone).toBeTruthy(); // log.quick({clone, obj}, clone.x.slice(0, 3), obj.x.slice(0, 3))
expect(clone.x.slice(0, 3)).toEqual([1, 2, 3]);
expect(clone.y.slice(0, 2)).toEqual([4, 5]);
});
test.skip('circClone - @FIXME', () => {
var obj = {
x: [1, 2, 3],
y: [4, 5]
};
obj.y[2] = obj;
obj.x.push(obj.y);
var clone = traverse.clone(obj);
log.quick(clone.x[3][2], clone); // expect(clone.y[2] === clone).toBeTruthy()
expect(eq(clone.y[2], clone)).toBeTruthy();
expect(eq(clone, clone.y[2])).toBeTruthy();
expect(eq(clone.x[3][2], clone)).toBeTruthy();
console.log(clone.y[2] !== obj);
console.log(clone.x[3][2] !== obj);
});
test.skip('circMapScrub', () => {
var obj = {
a: 1,
b: 2
};
obj.c = obj;
var scrubbed = traverse(obj).map(function (node) {
if (this.circular) this.remove();
});
expect(Object.keys(scrubbed).sort()).toEqual(['a', 'b']);
expect(deepEqual(scrubbed, {
a: 1,
b: 2
}, true)).toBeTruthy();
expect(deepEqual(obj.c, obj, true)).toBeTruthy();
});