UNPKG

auto-translatr

Version:
263 lines (262 loc) 12.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../utils"); describe('Either utilities', () => { describe('left and right constructors', () => { it('should create left value', () => { const result = (0, utils_1.left)('error message'); expect(result).toEqual({ type: 'left', value: 'error message' }); }); it('should create right value', () => { const result = (0, utils_1.right)('success value'); expect(result).toEqual({ type: 'right', value: 'success value' }); }); }); describe('isLeft and isRight type guards', () => { it('should identify left values', () => { const leftValue = (0, utils_1.left)('error'); expect((0, utils_1.isLeft)(leftValue)).toBe(true); expect((0, utils_1.isRight)(leftValue)).toBe(false); }); it('should identify right values', () => { const rightValue = (0, utils_1.right)('success'); expect((0, utils_1.isRight)(rightValue)).toBe(true); expect((0, utils_1.isLeft)(rightValue)).toBe(false); }); }); }); describe('chain function', () => { it('should chain successful operations with flatMap', () => { const addOne = (x) => (0, utils_1.right)(x + 1); const multiplyByTwo = (x) => (0, utils_1.right)(x * 2); const chained = (0, utils_1.lift)(addOne) .flatMap(multiplyByTwo); const result = chained.result(5); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe(12); // (5 + 1) * 2 = 12 } }); it('should transform values with map', () => { const addOne = (x) => (0, utils_1.right)(x + 1); const chained = (0, utils_1.lift)(addOne) .map(x => x * 2); const result = chained.result(5); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe(12); // (5 + 1) * 2 = 12 } }); it('should transform errors with mapError', () => { const failOperation = (x) => (0, utils_1.left)(`Failed at value: ${x}`); const chained = (0, utils_1.lift)(failOperation) .mapError(error => `Custom error: ${error}`); const result = chained.result(5); expect((0, utils_1.isLeft)(result)).toBe(true); if ((0, utils_1.isLeft)(result)) { expect(result.value).toBe('Custom error: Failed at value: 5'); } }); it('should handle errors in the middle of the chain', () => { const addOne = (x) => (0, utils_1.right)(x + 1); const failOperation = (x) => (0, utils_1.left)(`Failed at value: ${x}`); const chained = (0, utils_1.lift)(addOne) .flatMap(failOperation); const result = chained.result(5); expect((0, utils_1.isLeft)(result)).toBe(true); if ((0, utils_1.isLeft)(result)) { expect(result.value).toBe('Failed at value: 6'); } }); it('should handle exceptions in the chain', () => { const addOne = (x) => (0, utils_1.right)(x + 1); const throwError = (x) => { throw new Error(`Exception at value: ${x}`); }; const chained = (0, utils_1.lift)(addOne) .flatMap(throwError); const result = chained.result(5); expect((0, utils_1.isLeft)(result)).toBe(true); if ((0, utils_1.isLeft)(result)) { expect(result.value).toBeInstanceOf(Error); expect(result.value.message).toBe('Exception at value: 6'); } }); it('should handle empty chain', () => { const identity = (x) => (0, utils_1.right)(x); const chained = (0, utils_1.lift)(identity); const result = chained.result(42); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe(42); } }); it('should combine map and andThen', () => { const parseNumber = (str) => { const num = parseInt(str, 10); return isNaN(num) ? (0, utils_1.left)('Invalid number') : (0, utils_1.right)(num); }; const validatePositive = (num) => { return num > 0 ? (0, utils_1.right)(num) : (0, utils_1.left)('Number must be positive'); }; const chained = (0, utils_1.lift)(parseNumber) .map(num => num * 2) // Transform the number .flatMap(validatePositive); // Validate the transformed number // Test successful case const successResult = chained.result('5'); expect((0, utils_1.isRight)(successResult)).toBe(true); if ((0, utils_1.isRight)(successResult)) { expect(successResult.value).toBe(10); } // Test validation error const validationErrorResult = chained.result('-5'); expect((0, utils_1.isLeft)(validationErrorResult)).toBe(true); if ((0, utils_1.isLeft)(validationErrorResult)) { expect(validationErrorResult.value).toBe('Number must be positive'); } // Test parsing error const parseErrorResult = chained.result('abc'); expect((0, utils_1.isLeft)(parseErrorResult)).toBe(true); if ((0, utils_1.isLeft)(parseErrorResult)) { expect(parseErrorResult.value).toBe('Invalid number'); } }); it('should handle complex transformations', () => { const parseNumber = (str) => { const num = parseInt(str, 10); return isNaN(num) ? (0, utils_1.left)('Invalid number') : (0, utils_1.right)(num); }; const chained = (0, utils_1.lift)(parseNumber) .map(num => num * 2) // Double the number .map(num => num + 1) // Add 1 .mapError(error => `Parsing failed: ${error}`); // Transform error // Test successful case const successResult = chained.result('5'); expect((0, utils_1.isRight)(successResult)).toBe(true); if ((0, utils_1.isRight)(successResult)) { expect(successResult.value).toBe(11); // (5 * 2) + 1 = 11 } // Test error case with transformed error const errorResult = chained.result('abc'); expect((0, utils_1.isLeft)(errorResult)).toBe(true); if ((0, utils_1.isLeft)(errorResult)) { expect(errorResult.value).toBe('Parsing failed: Invalid number'); } }); }); it('should handle Promises', () => __awaiter(void 0, void 0, void 0, function* () { const readFile = () => Promise.resolve((0, utils_1.right)('file content')); const uppercase = (str) => str.toUpperCase(); const result = yield (0, utils_1.liftAsync)(readFile) .map(uppercase) .result(); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe('FILE CONTENT'); } })); it('should handle functions that do nothing', () => __awaiter(void 0, void 0, void 0, function* () { const readFile = () => Promise.resolve((0, utils_1.right)('file content')); const uppercase = (str) => str.toUpperCase(); const writeFile = (str) => Promise.resolve((0, utils_1.right)(undefined)); const result = yield (0, utils_1.liftAsync)(readFile) .map(uppercase) .flatMapVoid(writeFile) .result(); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe('FILE CONTENT'); } })); describe('AsyncMonad flatMapAll', () => { it('should collect all right values when all succeed', () => __awaiter(void 0, void 0, void 0, function* () { const start = (0, utils_1.liftAsync)((x) => __awaiter(void 0, void 0, void 0, function* () { return (0, utils_1.right)(x); })); const double = (n) => Promise.resolve((0, utils_1.right)(n * 2)); const triple = (n) => Promise.resolve((0, utils_1.right)(n * 3)); const result = yield start .flatMapAll(n => [double(n), triple(n)]) .result(5); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toEqual([10, 15]); } })); it('should return left if any promise is left', () => __awaiter(void 0, void 0, void 0, function* () { const start = (0, utils_1.liftAsync)((x) => __awaiter(void 0, void 0, void 0, function* () { return (0, utils_1.right)(x); })); const double = (n) => Promise.resolve((0, utils_1.right)(n * 2)); const fail = (_) => Promise.resolve((0, utils_1.left)('error')); const result = yield start .flatMapAll(n => [double(n), fail(n)]) .result(5); expect((0, utils_1.isLeft)(result)).toBe(true); if ((0, utils_1.isLeft)(result)) { expect(result.value).toBe('error'); } })); it('should work with an empty array', () => __awaiter(void 0, void 0, void 0, function* () { const start = (0, utils_1.liftAsync)((x) => __awaiter(void 0, void 0, void 0, function* () { return (0, utils_1.right)(x); })); const result = yield start .flatMapAll(_ => []) .result(5); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toEqual([]); } })); }); describe('AsyncMonad flatMapAllVoid', () => { it('should pass through original value if all succeed', () => __awaiter(void 0, void 0, void 0, function* () { const start = (0, utils_1.liftAsync)((x) => __awaiter(void 0, void 0, void 0, function* () { return (0, utils_1.right)(x); })); const succeed = (_) => Promise.resolve((0, utils_1.right)(undefined)); const result = yield start .flatMapAllVoid(n => [succeed(n), succeed(n)]) .result(42); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe(42); } })); it('should return left if any promise is left', () => __awaiter(void 0, void 0, void 0, function* () { const start = (0, utils_1.liftAsync)((x) => __awaiter(void 0, void 0, void 0, function* () { return (0, utils_1.right)(x); })); const succeed = (_) => Promise.resolve((0, utils_1.right)(undefined)); const fail = (_) => Promise.resolve((0, utils_1.left)('error')); const result = yield start .flatMapAllVoid(n => [succeed(n), fail(n)]) .result(42); expect((0, utils_1.isLeft)(result)).toBe(true); if ((0, utils_1.isLeft)(result)) { expect(result.value).toBe('error'); } })); it('should work with an empty array', () => __awaiter(void 0, void 0, void 0, function* () { const start = (0, utils_1.liftAsync)((x) => __awaiter(void 0, void 0, void 0, function* () { return (0, utils_1.right)(x); })); const result = yield start .flatMapAllVoid(_ => []) .result(42); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe(42); } })); it('should allow chaining after flatMapAllVoid', () => __awaiter(void 0, void 0, void 0, function* () { const start = (0, utils_1.liftAsync)((x) => __awaiter(void 0, void 0, void 0, function* () { return (0, utils_1.right)(x); })); const succeed = (_) => Promise.resolve((0, utils_1.right)(undefined)); const result = yield start .flatMapAllVoid(n => [succeed(n)]) .map(n => n + 1) .result(10); expect((0, utils_1.isRight)(result)).toBe(true); if ((0, utils_1.isRight)(result)) { expect(result.value).toBe(11); } })); });