You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
6.8 KiB
TypeScript
205 lines
6.8 KiB
TypeScript
import { expect } from 'chai';
|
|
import chai from 'chai';
|
|
import chaiAsPromised from 'chai-as-promised';
|
|
import { toString } from 'ramda';
|
|
import { arraySum, getArrayFromZeroOfLengthN, sleep, TimeUnit } from 'swiss-army-knifey';
|
|
import { combineReturns, composeWithPromise, simpleCombineReturns } from '../../src/utils/ramda';
|
|
|
|
chai.use(chaiAsPromised);
|
|
|
|
describe(`ramda style`, function() {
|
|
describe(`composeWithPromise(few functions)`, function() {
|
|
|
|
it('should await and return a composed result', async function() {
|
|
const paramToProp = (param: string) => ({ param });
|
|
const sleepingSentence = (s: number) => async ({ param }: { param: string }) => {
|
|
const d1 = new Date();
|
|
await sleep(s, TimeUnit.second);
|
|
const d2 = new Date();
|
|
return `a_[${param}], slept for: ${d2.getTime() - d1.getTime()}`;
|
|
};
|
|
const toUp = async (param: string) => param.toUpperCase();
|
|
const removeStart = async (param: string) => param.slice(1);
|
|
const composed = composeWithPromise(
|
|
removeStart,
|
|
sleepingSentence(1),
|
|
paramToProp,
|
|
toUp,
|
|
sleepingSentence(2),
|
|
paramToProp
|
|
);
|
|
return expect(composed('hey')).to.eventually.match(/_\[A_\[HEY\], SLEPT FOR: \d{4}\], slept for: \d{3,4}$/g);
|
|
});
|
|
|
|
it('should be able to compose non async functions', async function() {
|
|
const paramToProp = (param: string) => ({ param });
|
|
const toUp = (param: string) => param.toUpperCase();
|
|
const removeFirst = ({ param }: { param: string }) => param.slice(1);
|
|
const composed = composeWithPromise(
|
|
removeFirst,
|
|
paramToProp,
|
|
toUp,
|
|
toString
|
|
);
|
|
return expect(composed(3.14159)).to.equal('.14159');
|
|
});
|
|
|
|
it('should handle arrays of promises', async function() {
|
|
// [1, 2, 3] -> [Promise 1, Promise 4, Promise 9]
|
|
const asyncSquare = (ns: number[]) => {
|
|
return ns.map(async n => {
|
|
await sleep(1, TimeUnit.second);
|
|
return n * n;
|
|
})
|
|
};
|
|
// [1, 4, 9] -> [0, 6, 45]
|
|
const asyncSum = (ns: number[]) => {
|
|
return ns
|
|
// [1, 4, 9]
|
|
.map(getArrayFromZeroOfLengthN)
|
|
// [[0], [0, 1, 2, 3], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
|
|
.map(async (arr: number[]) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return arraySum(arr);
|
|
});
|
|
// [0, 6, 36]
|
|
};
|
|
const composed = composeWithPromise(
|
|
asyncSum,
|
|
asyncSquare,
|
|
);
|
|
|
|
return expect(composed([1, 2, 3])).to.eventually.deep.equal([0, 6, 36]);
|
|
});
|
|
|
|
it('should handle rejections', async function() {
|
|
// [1, 2, 3] -> [Promise 1, Promise 4, Promise 9]
|
|
const asyncSquare = (ns: number[]) => {
|
|
return ns.map(async n => {
|
|
await sleep(1, TimeUnit.second);
|
|
return n * n;
|
|
})
|
|
};
|
|
// [1, 4, 9] -> [0, 6, 45]
|
|
const asyncSum = (ns: number[]) => {
|
|
return ns
|
|
// [1, 4, 9]
|
|
.map(getArrayFromZeroOfLengthN)
|
|
// [[0], [0, 1, 2, 3], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
|
|
.map(async (arr: number[]) => {
|
|
await sleep(1, TimeUnit.second);
|
|
throw new Error('Woho rejected promise');
|
|
});
|
|
// [0, 6, 36]
|
|
};
|
|
|
|
const composed = composeWithPromise(
|
|
asyncSum,
|
|
asyncSquare,
|
|
);
|
|
|
|
return expect(composed([1, 2, 3])).to.eventually.be.rejectedWith('Woho rejected promise');
|
|
});
|
|
});
|
|
|
|
describe('simpleCombineReturns', () => {
|
|
|
|
it('should combine results of promise-returning functions with sleep delay', async () => {
|
|
const fn1 = async (num: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { value1: num + 1 };
|
|
};
|
|
const fn2 = async (num: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { value2: num * 2 };
|
|
};
|
|
|
|
const startTime = Date.now();
|
|
const result = await simpleCombineReturns([fn1, fn2], 10);
|
|
const endTime = Date.now();
|
|
|
|
expect(result).to.deep.equal({ value1: 11, value2: 20 });
|
|
expect(endTime - startTime).to.be.greaterThan(1000); // Check that at least 1 second has passed
|
|
});
|
|
|
|
it('should combine results of functions taking string inputs', async () => {
|
|
const fn1 = async (str: string) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { upper: str.toUpperCase() };
|
|
};
|
|
const fn2 = async (str: string) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { length: str.length };
|
|
};
|
|
|
|
const result = await simpleCombineReturns([fn1, fn2], "test");
|
|
expect(result).to.deep.equal({ upper: "TEST", length: 4 });
|
|
});
|
|
|
|
it('should combine results of functions returning different types', async () => {
|
|
const fn1 = async (value: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { boolValue: value > 10 };
|
|
};
|
|
const fn2 = async (value: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { stringValue: `Value is ${value}` };
|
|
};
|
|
|
|
const result = await simpleCombineReturns([fn1, fn2], 15);
|
|
expect(result).to.deep.equal({ boolValue: true, stringValue: "Value is 15" });
|
|
});
|
|
});
|
|
|
|
describe('combineReturns', () => {
|
|
it('should combine results of curried promise-returning functions with sleep delay', async () => {
|
|
const fn1 = async (num: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { value1: num + 1 };
|
|
};
|
|
const fn2 = async (num: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { value2: num * 2 };
|
|
};
|
|
|
|
const combined = combineReturns([fn1, fn2]);
|
|
const startTime = Date.now();
|
|
const result = await combined(10);
|
|
const endTime = Date.now();
|
|
|
|
expect(result).to.deep.equal({ value1: 11, value2: 20 });
|
|
expect(endTime - startTime).to.be.greaterThan(1000); // Check that at least 1 second has passed
|
|
});
|
|
|
|
it('should combine results of curried functions taking string inputs', async () => {
|
|
const fn1 = async (str: string) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { upper: str.toUpperCase() };
|
|
};
|
|
const fn2 = async (str: string) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { length: str.length };
|
|
};
|
|
|
|
const combined = combineReturns([fn1, fn2]);
|
|
const result = await combined("test");
|
|
expect(result).to.deep.equal({ upper: "TEST", length: 4 });
|
|
});
|
|
|
|
it('should combine results of curried functions returning different types', async () => {
|
|
const fn1 = async (value: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { boolValue: value > 10 };
|
|
};
|
|
const fn2 = async (value: number) => {
|
|
await sleep(1, TimeUnit.second);
|
|
return { stringValue: `Value is ${value}` };
|
|
};
|
|
|
|
const combined = combineReturns([fn1, fn2]);
|
|
const result = await combined(15);
|
|
expect(result).to.deep.equal({ boolValue: true, stringValue: "Value is 15" });
|
|
});
|
|
});
|
|
|
|
}); |