diff options
| author | EuAndreh <eu@euandre.org> | 2024-03-06 12:14:10 -0300 |
|---|---|---|
| committer | EuAndreh <eu@euandre.org> | 2024-03-06 12:14:10 -0300 |
| commit | f0d33b9b21b3c739ab20d8e2b60c39694350321a (patch) | |
| tree | 2a0eeeb6c3e133d43d6f94734d2ba7b642d6603a | |
| parent | src/utils.mjs: Add first(), rest(), butlast() and last() (diff) | |
| download | papod-f0d33b9b21b3c739ab20d8e2b60c39694350321a.tar.gz papod-f0d33b9b21b3c739ab20d8e2b60c39694350321a.tar.xz | |
src/hero.mjs: Add makeLineEmitter()
| -rw-r--r-- | src/hero.mjs | 19 | ||||
| -rw-r--r-- | tests/js/hero.mjs | 81 |
2 files changed, 100 insertions, 0 deletions
diff --git a/src/hero.mjs b/src/hero.mjs index 6b6fa77..8cbbe36 100644 --- a/src/hero.mjs +++ b/src/hero.mjs @@ -338,6 +338,25 @@ export const rmIf = path => { export const mkfifo = path => child_process.execFileSync("mkfifo", [path]); +export const makeLineEmitter = fn => { + let data = ""; + return chunk => { + const segments = chunk.split("\n"); + assert.ok(segments.length > 0); + + if (segments.length === 1) { + data += segments[0]; + return; + } + + [ + data + u.first(segments), + ...u.butlast(u.rest(segments)), + ].forEach(fn); + data = u.last(segments); + }; +}; + export const buildRoutes = (routes, globalInterceptors = []) => routes.reduce( (acc, [methods, path, handlerFn, interceptors = []]) => diff --git a/tests/js/hero.mjs b/tests/js/hero.mjs index ebb2c27..1debdc5 100644 --- a/tests/js/hero.mjs +++ b/tests/js/hero.mjs @@ -32,6 +32,7 @@ import { lineHandlerFn, rmIf, mkfifo, + makeLineEmitter, buildRoutes, promisifyServer, buildServer, @@ -1289,6 +1290,85 @@ const test_mkfifo = async t => { }); }; +const test_makeLineEmitter = async t => { + t.start("makeLineEmitter()"); + + await t.test("noop when we only get empty strings", async () => { + const entries = []; + const record = x => entries.push(x); + const emitter = makeLineEmitter(record); + + emitter(""); + emitter(""); + emitter(""); + emitter(""); + emitter(""); + + assert.deepEqual(entries, []); + }); + + await t.test("empty strings when we only get newlines", async () => { + const entries = []; + const record = x => entries.push(x); + const emitter = makeLineEmitter(record); + + emitter("\n\n\n"); + emitter("\n\n"); + emitter("\n"); + + assert.deepEqual(entries, [ "", "", "", "", "", "" ]); + }); + + await t.test("noop also if we never get a newline", async () => { + const entries = []; + const record = x => entries.push(x); + const emitter = makeLineEmitter(record); + + emitter(" "); + emitter("some string"); + emitter(" "); + emitter("a lot of text"); + assert.deepEqual(entries, []); + + emitter("\n"); + assert.deepEqual(entries, [ " some string a lot of text" ]); + }); + + await t.test("if a newline always comes, we always emit", async () => { + const entries = []; + const record = x => entries.push(x); + const emitter = makeLineEmitter(record); + + emitter("first\n"); + emitter("second\n"); + emitter("third\n"); + + assert.deepEqual(entries, [ "first", "second", "third" ]); + }); + + await t.test("lines can acummulate accross multiple writes", async () => { + const entries = []; + const record = x => entries.push(x); + const emitter = makeLineEmitter(record); + + emitter("fir"); + emitter("s"); + emitter("t\ns"); + emitter("econd\nthir"); + emitter("d"); + emitter("\n"); + emitter("fourth\nfifth\nsixth"); + + assert.deepEqual(entries, [ + "first", + "second", + "third", + "fourth", + "fifth", + ]); + }); +}; + const test_buildRoutes = async t => { t.start("buildRoutes()"); @@ -1523,6 +1603,7 @@ await runner.runTests([ test_buildRoutes, test_rmIf, test_mkfifo, + test_makeLineEmitter, test_promisifyServer, test_buildServer, ]); |
