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
172 lines (147 loc) • 4.63 kB
text/typescript
import { concatStream } from "./concats";
import { sflow } from "./sf";
describe("concats", () => {
const createStream = <T>(chunks: T[]): ReadableStream<T> => {
return new ReadableStream({
start(controller) {
for (const chunk of chunks) {
controller.enqueue(chunk);
}
controller.close();
},
});
};
it("should concatenate multiple streams correctly", async () => {
const source1 = createStream([1, 2, 3]);
const source2 = createStream([4, 5]);
const source3 = createStream([6, 7, 8, 9]);
const readable = concatStream([source1, source2, source3]);
const reader = readable.getReader();
const result: number[] = [];
let done = false;
while (!done) {
const { value, done: readerDone } = await reader.read();
if (!readerDone && value !== undefined) {
result.push(value);
}
done = readerDone;
}
expect(result).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
});
it("should concatenate multiple streams in correctly order", async () => {
const f = jest.fn();
const source1 = sflow([1, 2, 3]).forEach((e) => {
f(e);
});
const source2 = sflow([4, 5]).forEach((e) => {
f(e);
});
const source3 = sflow([6, 7, 8, 9]).forEach((e) => {
f(e);
});
const readable = concatStream([source1, source2, source3]);
const reader = readable.getReader();
const result: number[] = [];
const readOne = async () => {
const { value, done } = await reader.read();
if (done) return;
result.push(value);
return value;
};
expect(f).not.toHaveBeenCalled();
await readOne();
expect(f).toHaveBeenLastCalledWith(1);
await readOne();
expect(f).toHaveBeenLastCalledWith(2);
await readOne();
expect(f).toHaveBeenLastCalledWith(3);
await readOne();
expect(f).toHaveBeenLastCalledWith(4);
await readOne();
await readOne();
await readOne();
await readOne();
await readOne();
await readOne();
await readOne();
await readOne();
await readOne();
await readOne();
await readOne();
expect(result).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
});
it("should handle no streams", async () => {
const readable = concatStream();
const reader = readable.getReader();
const result: unknown[] = [];
let done = false;
while (!done) {
const { value, done: readerDone } = await reader.read();
if (!readerDone && value !== undefined) {
result.push(value);
}
done = readerDone;
}
expect(result).toEqual([]);
});
it("should handle a single stream", async () => {
const source1 = createStream([1, 2, 3]);
const readable = concatStream([source1]);
const reader = readable.getReader();
const result: number[] = [];
let done = false;
while (!done) {
const { value, done: readerDone } = await reader.read();
if (!readerDone && value !== undefined) {
result.push(value);
}
done = readerDone;
}
expect(result).toEqual([1, 2, 3]);
});
it("should support empty streams within the concatenation", async () => {
const source1 = createStream([1, 2, 3]);
const source2 = createStream([]);
const source3 = createStream([4, 5]);
const readable = concatStream([source1, source2, source3]);
const reader = readable.getReader();
const result: number[] = [];
let done = false;
while (!done) {
const { value, done: readerDone } = await reader.read();
if (!readerDone && value !== undefined) {
result.push(value);
}
done = readerDone;
}
expect(result).toEqual([1, 2, 3, 4, 5]);
});
it("should output the first stream before second stream starts", async () => {
const promise = Promise.withResolvers();
const source1 = createStream([1, 2, 3]);
const source2 = sflow([4, 5]).forEach(async () => {
await promise.promise;
return;
});
const readable = concatStream([source1, source2]);
const reader = readable.getReader();
const result: number[] = [];
const readOne = async () => {
const { value, done } = await reader.read();
if (done) return;
result.push(value);
return value;
};
await readOne();
expect(result).toEqual([1]);
await readOne();
expect(result).toEqual([1, 2]);
await readOne();
expect(result).toEqual([1, 2, 3]);
promise.resolve();
await readOne();
expect(result).toEqual([1, 2, 3, 4]);
await readOne();
expect(result).toEqual([1, 2, 3, 4, 5]);
});
});