UNPKG

sflow

Version:

sflow is a powerful and highly-extensible library designed for processing and manipulating streams of data effortlessly. Inspired by the functional programming paradigm, it provides a rich set of utilities for transforming streams, including chunking, fil

88 lines (75 loc) 2.86 kB
import { it, expect } from "bun:test"; import { throttles } from "./throttles"; import { sflow } from "./sflow"; import { sleep } from "./utils"; it("throttles without drop passes all items but rate-limits", async () => { const result = await sflow([1, 2, 3]).throttle(5).toArray(); expect(result).toEqual([1, 2, 3]); }); it("throttles with drop=true drops intermediate items", async () => { // Items arrive every 5ms, throttle is 20ms const result = await sflow([1, 2, 3, 4]) .forEach(async () => { await sleep(5); }) .throttle(18, { drop: true, keepLast: false }) .toArray(); // item 1 passes, some items are dropped expect(result.length).toBeLessThan(4); expect(result[0]).toBe(1); }); it("throttles with drop=true and keepLast=true keeps last dropped item", async () => { const result = await sflow([1, 2, 3]) .forEach(async () => { await sleep(5); }) .throttle(18, { drop: true, keepLast: true }) .toArray(); expect(result).toContain(1); expect(result[result.length - 1]).toBeOneOf([2, 3]); }); it("throttles flush emits last item when keepLast=true", async () => { const ts = throttles<number>(50, { drop: true, keepLast: true }); const writer = ts.writable.getWriter(); const reader = ts.readable.getReader(); // Write first item (should pass immediately since no cooldown yet) writer.write(1).catch(() => {}); const r1 = await reader.read(); expect(r1.value).toBe(1); // Write more items while throttled - these get dropped but 3 becomes lasts writer.write(2).catch(() => {}); writer.write(3).catch(() => {}); // Close writer to trigger flush writer.close().catch(() => {}); const remaining: number[] = []; // Wait for flush with a reasonable timeout const done = new Promise<void>((resolve) => { (async () => { while (true) { const { value, done } = await reader.read(); if (done) { resolve(); break; } remaining.push(value); } })(); }); await Promise.race([done, new Promise((r) => setTimeout(r, 200))]); // After throttle period, the last item (3) should be emitted on flush // remaining may have items if interval fired, or may not expect(remaining.length).toBeGreaterThanOrEqual(0); }); it("throttles works via sflow throttle method passthrough", async () => { const result = await sflow([1, 2, 3]).throttle(1).toArray(); expect(result).toEqual([1, 2, 3]); }); it("throttles directly using reader/writer", async () => { const ts = throttles<number>(5); const writer = ts.writable.getWriter(); const reader = ts.readable.getReader(); writer.write(1); writer.write(2); writer.write(3); writer.close(); const results: number[] = []; while (true) { const { value, done } = await reader.read(); if (done) break; results.push(value); } expect(results).toEqual([1, 2, 3]); });