Files
2026-04-27 13:19:17 +01:00

83 lines
2.0 KiB
JavaScript

import { describe, it, expect, vi } from 'vitest';
import { match, when, any } from '../js-fp3/library/patterns.js';
describe('when', () => {
it('returns a two-element tuple of [predicate, handler]', () => {
const predicate = () => true;
const handler = () => 'result';
const branch = when(predicate, handler);
expect(branch).toEqual([predicate, handler]);
});
});
describe('any', () => {
it('returns true for any value', () => {
expect(any(0)).toBe(true);
expect(any(null)).toBe(true);
expect(any('string')).toBe(true);
expect(any({ x: 1 })).toBe(true);
});
});
describe('match', () => {
it('executes the handler of the first matching branch', () => {
const result = match(
when((v) => v === 1, () => 'one'),
when((v) => v === 2, () => 'two'),
when(any, () => 'other')
)(1);
expect(result).toBe('one');
});
it('falls through to the next branch when the first does not match', () => {
const result = match(
when((v) => v === 1, () => 'one'),
when((v) => v === 2, () => 'two'),
when(any, () => 'other')
)(2);
expect(result).toBe('two');
});
it('uses the any catch-all when no earlier branch matches', () => {
const result = match(
when((v) => v === 1, () => 'one'),
when(any, () => 'catch-all')
)(99);
expect(result).toBe('catch-all');
});
it('passes the value to the handler', () => {
const result = match(
when(any, (v) => v * 2)
)(7);
expect(result).toBe(14);
});
it('throws when no branch matches', () => {
expect(() =>
match(
when((v) => v === 1, () => 'one')
)(99)
).toThrow('No matching pattern');
});
it('does not call handlers for branches that were not selected', () => {
const skipped = vi.fn(() => 'skipped');
const selected = vi.fn(() => 'selected');
match(
when((v) => v === 1, selected),
when(any, skipped)
)(1);
expect(selected).toHaveBeenCalledOnce();
expect(skipped).not.toHaveBeenCalled();
});
});