auto-translatr
Version:
An automatic translation library
263 lines (262 loc) • 12.7 kB
JavaScript
;
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);
}
}));
});