test(core:internal): test cases for Maybe and compose
MODIFY
jest.config.js
jest.config.js
@@ -18,7 +18,6 @@ module.exports = {
'@example',
'@integration',
'\\+internal/testing',
- '\\+internal/fp'
],
collectCoverageFrom : ['packages/**/*.ts'],
moduleFileExtensions: [

MODIFY
packages/core/src/+internal/fp/maybe.ts
packages/core/src/+internal/fp/maybe.ts
import { Functor } from './functor';
+export type Nullable<T> = T | null | undefined;
+
export interface MaybeCases<T, U> {
some: (t: T) => U;
none: () => U;
}
export class Maybe<T> implements Functor<T> {
- private constructor(private value: T | null | undefined) {}
+ private constructor(private value: Nullable<T>) {}
private static some = <T>(value: T) => new Maybe(value);
private static none = <T>() => new Maybe<T>(null);
- static of = <T>(value: T) =>
+ static of = <T>(value: Nullable<T>) =>
value
? Maybe.some(value)
: Maybe.none<T>()

ADD
packages/core/src/+internal/fp/spec/compose.spec.ts
+import { compose } from '../compose';
+
+describe('#compose', () => {
+ test('works correctly with more than 2 functions', () => {
+ // given
+ const add = (a: number) => (b: number) => b + a;
+ const substract = (a: number) => (b: number) => b - a;
+ const multiply = (a: number) => (b: number) => b * a;
+
+ // when
+ const result = compose(
+ multiply(2),
+ substract(2),
+ add(1),
+ )(10);
+
+ // then
+ expect(result).toEqual(18);
+ });
+
+ test('works correctly with 1 function', () => {
+ // given
+ const add = (a: number) => (b: number) => b + a;
+
+ // when
+ const result = compose(
+ add(1),
+ )(10);
+
+ // then
+ expect(result).toEqual(11);
+ });
+});

ADD
packages/core/src/+internal/fp/spec/maybe.spec.ts
+import { Maybe } from '../maybe';
+
+const increment = (v: number) => v + 1;
+
+describe('Maybe monad', () => {
+
+ describe('#valueOr', () => {
+ test('returns a defined value if Some', () => {
+ const value = Maybe.of(2)
+ .valueOr(0);
+
+ expect(value).toEqual(2);
+ });
+
+ test('returns provided default if None', () => {
+ const value = Maybe.of<number>(undefined)
+ .valueOr(0);
+
+ expect(value).toEqual(0);
+ });
+ });
+
+ describe('#valueOrCompute', () => {
+ test('returns a defined value if Some', () => {
+ const value = Maybe.of(2)
+ .valueOrCompute(() => 3);
+
+ expect(value).toEqual(2);
+ });
+
+ test('returns provided default if None', () => {
+ const value = Maybe.of<number>(undefined)
+ .valueOrCompute(() => 3);
+
+ expect(value).toEqual(3);
+ });
+ });
+
+
+ describe('#valueOrThrow', () => {
+ test('returns value if is Some', () => {
+ const value = () => Maybe.of(2)
+ .valueOrThrow();
+
+ expect(() => value()).not.toThrowError();
+ expect(value()).toEqual(2);
+ });
+
+ test('throws default error if None', () => {
+ const value = () => Maybe.of<number>(undefined)
+ .valueOrThrow();
+
+ expect(() => value()).toThrowError(new Error('No value is available'));
+ });
+
+ test('throws defined error if None', () => {
+ const value = () => Maybe.of<number>(undefined)
+ .valueOrThrow(new Error('test'));
+
+ expect(() => value()).toThrowError(new Error('test'));
+ });
+ });
+
+ describe('#map', () => {
+ test('maps value if Some', () => {
+ const value = Maybe.of(2)
+ .map(increment)
+ .valueOr(0);
+
+ expect(value).toEqual(3);
+ });
+
+ test('returns default if None', () => {
+ const value = Maybe.of<number>(undefined)
+ .map(increment)
+ .valueOr(0);
+
+ expect(value).toEqual(0);
+ });
+ });
+
+ describe('#flatMap', () => {
+ test('flattens Some monad and returns value', () => {
+ const value = Maybe.of(2)
+ .flatMap(v => Maybe.of('test'))
+ .valueOr('');
+
+ expect(value).toEqual('test');
+ });
+
+ test('flattens None monad and returns default', () => {
+ const value = Maybe.of<number>(undefined)
+ .flatMap(v => Maybe.of('test'))
+ .valueOr('test');
+
+ expect(value).toEqual('test');
+ });
+ });
+
+ describe('#caseOf', () => {
+ test('matches Some monad and returns value', () => {
+ const value = Maybe.of(2)
+ .caseOf({
+ some: v => v + 1,
+ none: () => 0,
+ });
+
+ expect(value).toEqual(3);
+ });
+
+ test('matches None monad and default value', () => {
+ const value = Maybe.of<number>(undefined)
+ .caseOf({
+ some: v => v + 1,
+ none: () => 0,
+ });
+
+ expect(value).toEqual(0);
+ });
+ });
+});

test(core:internal): test cases for Maybe and compose