functional/src/index.test.ts

258 lines
6.9 KiB
TypeScript

import { always, and, at, attr, bool, cmp, first, fmap, identity, is, isinstance, last, never, nn, nnu, nop, not, nu, or, partial, pipe, second, third } from "./index";
describe(nop, () => {
it("does nothing", () => {
expect(nop()).toBeUndefined();
});
});
describe(identity, () => {
it("returns the argument untouched", () => {
expect(identity(5)).toBe(5);
expect(identity(null)).toBe(null);
});
});
describe(partial, () => {
it("applies systematically fixed configuration", () => {
const func = (conf: { a: number, b: string, c: number }) => `${conf.a}${conf.b}${conf.c}`;
const pfunc = partial({ b: "test" }, func);
expect(pfunc({ a: 5, c: 8 })).toEqual("5test8");
});
it("pass through remaining arguments", () => {
const func = (conf: { a: number, b: string }, c: number) => `${conf.a}${conf.b}${c}`;
const pfunc = partial({ b: "test" }, func);
expect(pfunc({ a: 2 }, 3)).toEqual("2test3");
});
});
describe(cmp, () => {
it("simplifies array sorting", () => {
expect([8, 3, 5].sort(cmp())).toEqual([3, 5, 8]);
expect([8, 3, 5, 8].sort(cmp({ reverse: true }))).toEqual([8, 8, 5, 3]);
expect([-2, 8, -7].sort(cmp({ key: Math.abs }))).toEqual([-2, -7, 8]);
expect(["c", "a", "b"].sort(cmp())).toEqual(["a", "b", "c"]);
});
});
describe(always, () => {
it("returns true", () => {
expect(always()).toBe(true);
expect(always(true)).toBe(true);
expect(always(false)).toBe(true);
});
});
describe(never, () => {
it("returns false", () => {
expect(never()).toBe(false);
expect(never(true)).toBe(false);
expect(never(false)).toBe(false);
});
});
describe(not, () => {
it("negates predicate", () => {
const iseven = (x: number) => x % 2 == 0;
const isodd = not(iseven);
expect(iseven(0)).toBe(true);
expect(isodd(0)).toBe(false);
expect(iseven(1)).toBe(false);
expect(isodd(1)).toBe(true);
expect(iseven(2)).toBe(true);
expect(isodd(2)).toBe(false);
});
});
describe(and, () => {
it("combines predicates", () => {
const f = and((x: number) => x % 2 == 0, (x: number) => x > 5);
expect(f(0)).toBe(false);
expect(f(2)).toBe(false);
expect(f(8)).toBe(true);
expect(f(9)).toBe(false);
expect(f(10)).toBe(true);
});
});
describe(or, () => {
it("combines predicates", () => {
const f = or((x: number) => x % 2 == 0, (x: number) => x > 5);
expect(f(0)).toBe(true);
expect(f(1)).toBe(false);
expect(f(2)).toBe(true);
expect(f(8)).toBe(true);
expect(f(9)).toBe(true);
});
});
describe(is, () => {
it("checks for equality", () => {
const f = is(5);
expect(f(5)).toBe(true);
expect(f(4)).toBe(false);
expect(f("a" as any)).toBe(false);
expect(f(null as any)).toBe(false);
expect(f(undefined as any)).toBe(false);
});
it("applies strict equality", () => {
const obj: { x: number } = { x: 1 };
let f = is(obj);
expect(f(obj)).toBe(true);
expect(f({ x: 1 })).toBe(false);
expect(f({ y: 1 } as any)).toBe(false);
});
});
describe(isinstance, () => {
it("checks for subclasses", () => {
class A { }
class A1 extends A { }
class A2 extends A { }
class B { }
const f: any[] = [5, null, undefined, new A, new A1, new B, new A2];
const result = f.filter(isinstance(A));
expect(result).toEqual([f[3], f[4], f[6]]);
});
});
describe(pipe, () => {
it("pipes two functions", () => {
const f = pipe((x: number) => x * 2, (x: number) => x + 1);
expect(f(1)).toBe(3);
expect(f(2)).toBe(5);
expect(f(3)).toBe(7);
});
});
describe(attr, () => {
it("gets an attribute from an object", () => {
const getx = attr("x");
expect(getx({ x: 4, y: 5 })).toBe(4);
expect(getx({ x: undefined, y: 5 })).toBeUndefined();
});
});
describe(at, () => {
it("gets an index in an array", () => {
const second = at(1);
expect(second([1, 4, 8])).toBe(4);
expect(second([1])).toBeUndefined();
});
it("handles negative indices from the end", () => {
const second_from_end = at(-2);
expect(second_from_end([1, 4, 6, 8])).toBe(6);
expect(second_from_end([1])).toBeUndefined();
});
});
describe(first, () => {
it("gets the first item in an array", () => {
expect(first([1, 4, 8])).toBe(1);
expect(first([1])).toBe(1);
expect(first([])).toBeUndefined();
});
});
describe(second, () => {
it("gets the second item in an array", () => {
expect(second([1, 4, 8])).toBe(4);
expect(second([1])).toBeUndefined();
expect(second([])).toBeUndefined();
});
});
describe(third, () => {
it("gets the third item in an array", () => {
expect(third([1, 4, 8])).toBe(8);
expect(third([1, 4])).toBeUndefined();
expect(third([])).toBeUndefined();
});
});
describe(last, () => {
it("gets the last item in an array", () => {
expect(last([1, 4, 8])).toBe(8);
expect(last([1])).toBe(1);
expect(last([])).toBeUndefined();
});
});
describe(nn, () => {
it("checks for null", () => {
expect(nn(undefined)).toBeUndefined();
expect(nn(0)).toBe(0);
expect(nn("")).toBe("");
expect(nn([])).toEqual([]);
expect(() => nn(null)).toThrowError("null value");
});
});
describe(nu, () => {
it("checks for undefined", () => {
expect(nu(null)).toBe(null);
expect(nu(0)).toBe(0);
expect(nu("")).toBe("");
expect(nu([])).toEqual([]);
expect(() => nu(undefined)).toThrowError("undefined value");
});
});
describe(nnu, () => {
it("checks for null or undefined", () => {
expect(nnu(0)).toBe(0);
expect(nnu("")).toBe("");
expect(nnu([])).toEqual([]);
expect(() => nnu(undefined)).toThrowError("undefined value");
expect(() => nnu(null)).toThrowError("null value");
});
});
describe(bool, () => {
it("checks for boolean equivalent", () => {
expect(bool(null)).toBe(false);
expect(bool(undefined)).toBe(false);
expect(bool(false)).toBe(false);
expect(bool(true)).toBe(true);
expect(bool(-1)).toBe(true);
expect(bool(0)).toBe(false);
expect(bool(1)).toBe(true);
expect(bool("")).toBe(false);
expect(bool(" ")).toBe(true);
expect(bool("abc")).toBe(true);
expect(bool([])).toBe(false);
expect(bool([0])).toBe(true);
expect(bool([1, 2, 3])).toBe(true);
expect(bool(new Set())).toBe(false);
expect(bool(new Set([0]))).toBe(true);
expect(bool(new Set([1, 2, 3]))).toBe(true);
expect(bool({})).toBe(false);
expect(bool({ a: 5 })).toBe(true);
class Obj1 { };
class Obj2 { private x = 0 };
expect(bool(new Obj1())).toBe(false);
expect(bool(new Obj2())).toBe(true);
});
});
describe(fmap, () => {
it("applies map and filter on an array", () => {
expect(fmap()([1, 2, 3])).toEqual([1, 2, 3]);
expect(fmap((x: number) => x * 2)([1, 2, 3])).toEqual([2, 4, 6]);
expect(fmap(undefined, (x: number) => x % 2 == 0)([1, 2, 3])).toEqual([2]);
expect(fmap((x: number) => x * 2)([1, 2, 3])).toEqual([2, 4, 6]);
expect(fmap((x: number) => x * 2, (x: number) => x < 5)([1, 2, 3])).toEqual([2, 4]);
});
});