Skip to content

Commit 83233ff

Browse files
committed
Add support for listening to external EventTargets
1 parent 504d0dc commit 83233ff

File tree

3 files changed

+235
-29
lines changed

3 files changed

+235
-29
lines changed

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
test_node_14:
2+
asdf install nodejs 14.17.6
3+
source $(ASDF_DIR)/asdf.sh && asdf shell nodejs 14.17.6 && npm t
4+
5+
test_node_15:
6+
@asdf install nodejs 15.14.0
7+
source $(ASDF_DIR)/asdf.sh && asdf shell nodejs 15.14.0 && npm t

src/index.test.ts

Lines changed: 149 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
import { always, compound, cond, entry, exit, on, start } from "./index";
1+
/**
2+
* @jest-environment jsdom
3+
*/
4+
5+
import {
6+
always,
7+
compound,
8+
cond,
9+
entry,
10+
exit,
11+
on,
12+
listenTo,
13+
send,
14+
start,
15+
} from "./index";
16+
17+
test("node version " + process.version, () => {});
218

319
const fetch = jest.fn();
420
beforeEach(fetch.mockClear);
@@ -64,7 +80,9 @@ describe("Machine with entry and exit actions", () => {
6480
expect(finishedLoading).toHaveBeenCalledTimes(0);
6581

6682
await expect(loader.results).resolves.toEqual({ fetchData: 42 });
67-
await expect(Promise.resolve(transitionResult)).resolves.toEqual({ fetchData: 42 });
83+
await expect(Promise.resolve(transitionResult)).resolves.toEqual({
84+
fetchData: 42,
85+
});
6886
expect(finishedLoading).toHaveBeenCalledTimes(1);
6987
expect(loader.changeCount).toEqual(2);
7088
expect(loader.current).toEqual("success");
@@ -130,7 +148,7 @@ describe.skip("Fetch with abort signal", () => {
130148
}
131149

132150
function Loader() {
133-
const aborterKey = Symbol('aborter');
151+
const aborterKey = Symbol("aborter");
134152
// yield register(aborterKey, () => new AbortController());
135153
// yield register(function aborter() { return new AbortController() });
136154

@@ -188,7 +206,9 @@ describe.skip("Fetch with abort signal", () => {
188206
expect(finishedLoading).toHaveBeenCalledTimes(0);
189207

190208
await expect(loader.results).resolves.toEqual({ fetchData: 42 });
191-
await expect(Promise.resolve(transitionResult)).resolves.toEqual({ fetchData: 42 });
209+
await expect(Promise.resolve(transitionResult)).resolves.toEqual({
210+
fetchData: 42,
211+
});
192212
expect(finishedLoading).toHaveBeenCalledTimes(1);
193213
expect(loader.changeCount).toEqual(2);
194214
expect(loader.current).toEqual("success");
@@ -372,27 +392,27 @@ describe("Hierarchical Traffic Lights Machine", () => {
372392
expect(machine.changeCount).toEqual(1);
373393

374394
machine.next("TIMER");
375-
expect(machine.current).toEqual({ "red": "walk" });
395+
expect(machine.current).toEqual({ red: "walk" });
376396
// expect(machine.current).toEqual([["red", "walk"]]); // Like a Map key
377397
// expect(machine.currentMap).toEqual(new Map([["red", "walk"]]));
378398
expect(machine.changeCount).toEqual(3);
379399

380400
machine.next("TIMER");
381401
expect(machine.current).toEqual("green");
382402
expect(machine.changeCount).toEqual(4);
383-
403+
384404
machine.next("POWER_RESTORED");
385-
expect(machine.current).toEqual({ "red": "walk" });
405+
expect(machine.current).toEqual({ red: "walk" });
386406
expect(machine.changeCount).toEqual(6);
387-
407+
388408
machine.next("POWER_OUTAGE");
389-
expect(machine.current).toEqual({ "red": "blinking" });
409+
expect(machine.current).toEqual({ red: "blinking" });
390410
expect(machine.changeCount).toEqual(7);
391411
});
392412
});
393413

394414
describe("Switch", () => {
395-
function* Switch() {
415+
function Switch() {
396416
function* OFF() {
397417
yield on("FLICK", ON);
398418
}
@@ -419,9 +439,9 @@ describe("Switch", () => {
419439
});
420440

421441
describe("Switch with symbol messages", () => {
422-
const FLICK = Symbol('FLICK');
442+
const FLICK = Symbol("FLICK");
423443

424-
function* Switch() {
444+
function Switch() {
425445
function* OFF() {
426446
yield on(FLICK, ON);
427447
}
@@ -445,12 +465,128 @@ describe("Switch with symbol messages", () => {
445465
expect(machine.current).toEqual("OFF");
446466
expect(machine.changeCount).toEqual(2);
447467

448-
machine.next(Symbol('will be ignored'));
468+
machine.next(Symbol("will be ignored"));
449469
expect(machine.current).toEqual("OFF");
450470
expect(machine.changeCount).toEqual(2);
451471
});
452472
});
453473

474+
describe("Wrapping AbortController as a state machine", () => {
475+
function AbortSender(controller: AbortController) {
476+
function* initial() {
477+
yield cond(controller.signal.aborted, aborted);
478+
yield on("abort", aborted);
479+
}
480+
function* aborted() {
481+
// yield entry(controller.abort.bind(controller));
482+
yield entry(function abort() {
483+
controller.abort();
484+
});
485+
}
486+
487+
return initial;
488+
}
489+
490+
function AbortListener(controller: AbortController) {
491+
function* initial() {
492+
if (controller.signal.aborted) {
493+
yield always(aborted);
494+
} else {
495+
yield on("abort", aborted);
496+
yield listenTo(controller.signal, "abort");
497+
}
498+
}
499+
function* aborted() {}
500+
501+
return initial;
502+
}
503+
504+
function AbortOwner() {
505+
// const controllerKey = Symbol('AbortController');
506+
function controller() {
507+
return new AbortController();
508+
}
509+
510+
function* initial() {
511+
yield entry(controller);
512+
yield on("abort", aborted);
513+
}
514+
function* aborted() {
515+
yield entry(send(controller, "abort", []));
516+
}
517+
518+
return initial;
519+
}
520+
521+
describe("AbortSender", () => {
522+
it("is already aborted if passed controller is aborted", () => {
523+
const aborter = new AbortController();
524+
aborter.abort();
525+
const machine = start(AbortSender.bind(null, aborter));
526+
expect(machine.current).toEqual("aborted");
527+
expect(machine.changeCount).toEqual(0);
528+
});
529+
530+
it("tells AbortController to abort", () => {
531+
const aborter = new AbortController();
532+
const machine = start(AbortSender.bind(null, aborter));
533+
534+
expect(machine.current).toEqual("initial");
535+
expect(machine.changeCount).toEqual(0);
536+
537+
expect(aborter.signal.aborted).toBe(false);
538+
539+
machine.next("abort");
540+
expect(machine.current).toEqual("aborted");
541+
expect(machine.changeCount).toEqual(1);
542+
543+
expect(aborter.signal.aborted).toBe(true);
544+
});
545+
});
546+
547+
describe("AbortListener", () => {
548+
it("is already aborted if passed controller is aborted", () => {
549+
const aborter = new AbortController();
550+
aborter.abort();
551+
const machine = start(AbortListener.bind(null, aborter));
552+
expect(machine.current).toEqual("aborted");
553+
expect(machine.changeCount).toEqual(0);
554+
});
555+
556+
it("listens when AbortController aborts", () => {
557+
const aborter = new AbortController();
558+
const machine = start(AbortListener.bind(null, aborter));
559+
560+
expect(machine.current).toEqual("initial");
561+
expect(machine.changeCount).toEqual(0);
562+
expect(aborter.signal.aborted).toBe(false);
563+
564+
aborter.abort();
565+
expect(machine.current).toEqual("aborted");
566+
expect(machine.changeCount).toEqual(1);
567+
});
568+
});
569+
570+
describe("AbortOwner", () => {
571+
it("aborts", async () => {
572+
const machine = start(AbortOwner);
573+
574+
expect(machine.current).toEqual("initial");
575+
expect(machine.changeCount).toEqual(0);
576+
577+
const { controller } = await machine.results as { controller: AbortController };
578+
expect(controller).toBeInstanceOf(AbortController);
579+
expect(controller.signal.aborted).toBe(false);
580+
581+
machine.next("abort");
582+
expect(machine.current).toEqual("aborted");
583+
expect(machine.changeCount).toEqual(1);
584+
585+
expect(controller.signal.aborted).toBe(true);
586+
});
587+
});
588+
});
589+
454590
/*describe("Counter", () => {
455591
function* Counter() {
456592
function* initial() {

0 commit comments

Comments
 (0)