asclasit
Version:
ASync CLasses + ASync ITerators
389 lines (332 loc) • 14.5 kB
JavaScript
const cr = require('crypto');
const Iter = require('./value');
require('./make');
require('./map');
require('./object');
const $ = require('../func');
require('../func2/promise');
test('Iter_.appendArray: tee to array', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const array = [];
wrapped.appendArray(array);
expect(Array.from(wrapped)).toEqual([2, 6, 7, 6]);
expect(array).toEqual([2, 6, 7, 6]);
});
test('Iter_.toArray: grab to array', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const array = wrapped.toArray();
expect(array).toEqual([2, 6, 7, 6]);
});
test('Iter_.toArray: append to array', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const to = [];
expect(wrapped.toArray(to)).toBe(to);
expect(to).toEqual([2, 6, 7, 6]);
});
test('Iter_.prependArray: tee to array from start / reversed', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const array = [];
wrapped.prependArray(array);
expect(Array.from(wrapped)).toEqual([2, 6, 7, 6]);
expect(array).toEqual([6, 7, 6, 2]);
});
test('Iter_.toPrependArray: grab to array reversed', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const array = wrapped.toPrependArray();
expect(array).toEqual([6, 7, 6, 2]);
});
test('Iter_.toPrependArray: prepend to array reversed', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const to = [];
expect(wrapped.toPrependArray(to)).toBe(to);
expect(to).toEqual([6, 7, 6, 2]);
});
test('Iter_.appendSet: tee to set', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const to = new Set();
wrapped.appendSet(to);
expect(Array.from(wrapped)).toEqual([2, 6, 7, 6]);
expect(Array.from(to)).toEqual([2, 6, 7]);
});
test('Iter_.unset: unset from Set or Map', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const to = new Set([1, 2, 6, 10]);
wrapped.unset(to);
expect(Array.from(wrapped)).toEqual([2, 6, 7, 6]);
expect(Array.from(to)).toEqual([1, 10]);
});
test('Iter_.toSet: grab to set', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const set = wrapped.toSet();
expect(Array.from(set)).toEqual([2, 6, 7]);
});
test('Iter_.toSet: append to set', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const to = new Set();
expect(wrapped.toSet(to)).toBe(to);
expect(Array.from(to)).toEqual([2, 6, 7]);
});
test('Iter_.appendXorSet: tee and xor to set', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const to = new Set();
wrapped.appendXorSet(to);
expect(Array.from(wrapped)).toEqual([true, true, true, false]);
expect(Array.from(to)).toEqual([2, 7]);
});
test('Iter_.appendXorSet: only detect xor operations', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
wrapped.appendXorSet();
expect(Array.from(wrapped)).toEqual([true, true, true, false]);
});
test('Iter_.toXorSet: xor to set', () => {
const wrapped = new Iter([2, 6, 7, 6][Symbol.iterator]());
const set = wrapped.toXorSet();
expect(Array.from(set)).toEqual([2, 7]);
});
test('Iter_.appendObject: tee object from entries', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const to = Object.create(null);
wrapped.appendObject(to, true);
expect(Object.fromEntries(wrapped)).toEqual({a: 1, b: 2, c: true});
expect(to).toEqual({a: 1, b: 2, c: true});
});
test('Iter_.omit: omit from object', () => {
const wrapped = new Iter(['a', 'b', ['c']][Symbol.iterator]());
const to = {a: 5, d: 8, x: 1, c: 2};
wrapped.omit(to);
expect(Array.from(wrapped)).toEqual(['a', 'b', ['c']]);
expect(to).toEqual({d: 8, x: 1});
});
test('Iter_.toObject: get object from entries', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
expect(entries.toObject(true)).toEqual({a: 1, b: 2, c: true});
});
test('Iter_.toObject: get object from entries with default', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
expect(entries.toObject(null, false)).toEqual({a: 1, b: 2, c: false});
});
test('Iter_.defaultsObject: tee to defaults object from entries', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', {b: 2}, null][Symbol.iterator]());
const to = {b: 8, null: 6};
wrapped.defaultsObject(null, false).defaultsObject(to);
expect(Object.fromEntries(wrapped)).toEqual({a: 1, b: 2, c: false});
expect(to).toEqual({a: 1, b: 8, c: false, null: 6});
});
test('Iter_.toDefaultsObject: get to object from entries', () => {
const entries = new Iter([['a', 1], {b: 0}, 'c', ['b', 2], null][Symbol.iterator]());
expect(entries.toDefaultsObject(true)).toEqual({a: 1, b: 0, c: true});
});
test('Iter_.toDefaultsObject: get to object from entries: explicit null spec', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
expect(entries.toDefaultsObject(null, true)).toEqual({a: 1, b: 0, c: true});
});
test('Iter_.toDefaultsObject: get to defaults object from entries', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const to = {a: 'hi', c: 4};
expect(entries.toDefaultsObject(to, true)).toEqual({a: 'hi', b: 0, c: 4});
});
test('Iter_.appendXorObject: tee and xor to object from entries', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const to = Object.create(null);
wrapped.appendXorObject(to, true);
expect(Array.from(wrapped)).toEqual([true, true, true, false, true]);
expect(to).toEqual({a: 1, c: true, null: true});
});
test('Iter_.appendXorObject: only detect xor operations', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
wrapped.appendXorObject(true);
expect(Array.from(wrapped)).toEqual([true, true, true, false, true]);
});
test('Iter_.appendXorObject: only detect xor operations', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
wrapped.appendXorObject(null, true);
expect(Array.from(wrapped)).toEqual([true, true, true, false, true]);
});
test('Iter_.toXorObject: xor to object from entries', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], 'c', null][Symbol.iterator]());
expect(entries.toXorObject(true)).toEqual({a: 1, null: true});
});
test('Iter_.toXorObject: xor to object from entries', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], 'c', null][Symbol.iterator]());
expect(entries.toXorObject(null, true)).toEqual({a: 1, null: true});
});
test('Iter_.appendMap: tee map from entries', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const to = new Map();
wrapped.appendMap(to, true);
expect(Object.fromEntries(wrapped)).toEqual({a: 1, b: 2, c: true, null: true});
expect(Object.fromEntries(to)).toEqual({a: 1, b: 2, c: true, null: true});
});
test('Iter_.toMap: get map from entries', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const map = entries.toMap(true);
expect(map instanceof Map).toBe(true);
expect(Object.fromEntries(map)).toEqual({a: 1, b: 2, c: true, null: true});
});
test('Iter_.defaultsMap: tee to defaults map from entries', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const to = new Map([['c', 'cc'], ['a', 3]]);
wrapped.defaultsMap(to, true);
expect(Object.fromEntries(wrapped)).toEqual({a: 1, b: 2, c: true, null: true});
expect(Object.fromEntries(to)).toEqual({a: 3, b: 0, c: 'cc', null: true});
});
test('Iter_.toDefaultsMap: get to defaults map from entries', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const map = entries.toDefaultsMap(true);
expect(map instanceof Map).toBe(true);
expect(Object.fromEntries(map)).toEqual({a: 1, b: 0, c: true, null: true});
});
test('Iter_.appendXorMap: tee and xor to map from entries', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
const to = new Map();
wrapped.appendXorMap(to, true);
expect(Array.from(wrapped)).toEqual([true, true, true, false, true]);
expect(Object.fromEntries(to)).toEqual({a: 1, c: true, null: true});
});
test('Iter_.appendXorMap: only detect xor operations', () => {
const wrapped = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], null][Symbol.iterator]());
wrapped.appendXorMap(true);
expect(Array.from(wrapped)).toEqual([true, true, true, false, true]);
});
test('Iter_.toXorMap: xor to map from entries', () => {
const entries = new Iter([['a', 1], ['b', 0], 'c', ['b', 2], 'a', null, 'a'][Symbol.iterator]());
const map = entries.toXorMap(true);
expect(map instanceof Map).toBe(true);
expect(Object.fromEntries(map)).toEqual({a: true, c: true, null: true});
});
test('Iter_.count: count iterator items', () => {
const wrapped = new Iter([2, 6, 7][Symbol.iterator]());
expect(wrapped.count()).toEqual(3);
});
test('Iter_.countTo: count iterator items on field', () => {
const result = {count: 0, next: 9};
const wrapped = new Iter([2, 6, 7][Symbol.iterator]());
wrapped.countTo(result).countTo(result, 'next').exec();
expect(result.count).toEqual(3);
expect(result.next).toEqual(12);
});
test('Iter_.exec: execute iterator', () => {
const wrapped = new Iter([2, 6, 7][Symbol.iterator]());
expect(wrapped.exec()).toEqual(undefined);
});
test('Iter_.first: empty', () => {
const wrapped = new Iter([][Symbol.iterator]());
expect(wrapped.first()).toEqual(undefined);
});
test('Iter_.first: get only first item', () => {
const wrapped = new Iter([2, 6, 7][Symbol.iterator]());
expect(wrapped.first()).toEqual(2);
});
test('Iter_.last: get only last item', () => {
const wrapped = new Iter([2, 6, 7][Symbol.iterator]());
expect(wrapped.last()).toEqual(7);
});
test('Iter_.reduce: add nothing', () => {
const wrapped = new Iter([][Symbol.iterator]());
const out = Object.create(null);
expect(wrapped.reduce($.sum, null, out)).toEqual(undefined);
expect(out).toEqual({});
});
test('Iter_.reduce: multiply numbers', () => {
const wrapped = new Iter([1, 2, 3, 4, 5][Symbol.iterator]());
const out = Object.create(null);
expect(wrapped.reduce($.prod, null, out)).toEqual(120);
expect(out).toEqual({count: 5, result: 120});
});
test('Iter_.reduce: concat strings', () => {
const wrapped = new Iter(['a', 'b', 'c', 'hello'][Symbol.iterator]());
const out = Object.create(null);
expect(wrapped.reduce(null, null, out)).toEqual('abchello');
expect(out).toEqual({count: 4, result: 'abchello'});
});
test('Iter_.toIter: duplicate iter', () => {
const from = new Iter([1, 2, 3][Symbol.iterator]());
const to = from.toIter();
expect(to !== from).toBe(true);
expect(to instanceof Iter).toBe(true);
expect(Array.from(to)).toEqual([1, 2, 3]);
});
class Quoter extends Iter {
*$_quote_(iter) {
for (const item of iter) {
yield `"${item}"`;
}
}
*$_tick_(iter) {
for (const item of iter) {
yield `'${item}'`;
}
}
$_spaced(iter) {
const m = Iter.from(iter).maps(v => [' ', v]);
m.ffwd(1);
return m.reduce();
}
}
test('Iter_.to: cast to subclass', () => {
const from = new Iter([1, 2, 3][Symbol.iterator]());
const to = from.to(Quoter);
expect(to !== from).toBe(true);
expect(to instanceof Iter).toBe(true);
expect(to instanceof Quoter).toBe(true);
expect(to.$).toBe(Quoter);
expect(Array.from(to.quote().tick())).toEqual([`'"1"'`, `'"2"'`, `'"3"'`]);
expect(Quoter.from([1, 2, 3]).spaced()).toBe('1 2 3');
});
test('$.feedback: return', () => {
const fb = new Iter(function* () { yield 1; yield 2; } ()).feedback();
expect(fb.next()).toEqual({value: 1, done: false});
expect(fb.return()).toEqual({done: true});
});
test('$.feedback: throw', () => {
const fb = new Iter(function* () { yield 1; yield 2; } ()).feedback();
expect(fb.next()).toEqual({value: 1, done: false});
expect(() => fb.throw(new Error('break'))).toThrow('break');
});
async function asItArray(iter) {
const res = [];
for await (const item of iter) res.push(item);
return res;
}
test('Iter_.stream: pipe to duplex stream', async () => {
const stream = Iter.range(5).map($.string).stream(cr.createCipheriv('bf-cbc', '1234', '12345678'));
const crypted = Iter.from(await asItArray(stream)).map(v => v.toString('hex')).reduce();
expect(stream.constructor.name).toBe('Cipheriv');
expect(crypted).toBe('68422a8db6cd9371');
});
test('Iter_.streams: partially pipe to duplex stream', async () => {
const cipher = cr.createCipheriv('bf-cbc', '1234', '12345678');
const out = Object.create(null);
const stream = Iter.range(5).map($.string).streams(cipher, out);
await $.finishedRead(out.stream);
const stream2 = Iter.range(5).map($.string).stream().pipe(cipher);
await $.finishedWrite(stream2);
const crypted = Iter.from(await asItArray(stream2)).map($.string_('hex')).reduce();
expect(crypted).toBe('7f04e1fa59d4c6b6e13fd4493d9d6c8a');
expect(stream).toBe(cipher);
expect(stream2).toBe(cipher);
});
class Custom {
constructor(config) { Object.assign(this, config); }
}
test('Iter_.appendResult: ', () => {
const iter = Iter.from([1, 2, 3, 4]);
const array = [];
const set = new Set();
const object = {};
const map = new Map();
const custom = new Custom();
iter.appendResult(array).appendResult(set).appendResult(object, 1).appendResult(map, 1).appendResult(custom, 1).exec();
expect(array).toEqual([1, 2, 3, 4]);
expect(Array.from(set)).toEqual([1, 2, 3, 4]);
expect(object).toEqual({1: 1, 2: 1, 3: 1, 4: 1});
expect(map).toEqual(new Map([[1, 1], [2, 1], [3, 1], [4, 1]]));
expect(custom).toEqual({1: 1, 2: 1, 3: 1, 4: 1});
});
test('Iter_.toResult: ', () => {
expect(Iter.from([1, 2, 3, 4]).toResult([])).toEqual([1, 2, 3, 4]);
expect(Iter.from([1, 2, 3, 4]).toResult(new Set())).toEqual(new Set([1, 2, 3, 4]));
expect(Iter.from([1, 2, 3, 4]).toResult($(), 1)).toEqual({1: 1, 2: 1, 3: 1, 4: 1});
expect(Iter.from([1, 2, 3, 4]).toResult(new Map(), 1)).toEqual(new Map([[1, 1], [2, 1], [3, 1], [4, 1]]));
expect(Iter.from([1, 2, 3, 4]).toResult(new Custom(), 1)).toEqual({1: 1, 2: 1, 3: 1, 4: 1});
});