Skip to content

Commit b1a964b

Browse files
committed
Moar test coverage!
1 parent 4c0e9aa commit b1a964b

File tree

9 files changed

+627
-0
lines changed

9 files changed

+627
-0
lines changed

bin/cjs/index.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"use strict";
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
var desc = Object.getOwnPropertyDescriptor(m, k);
5+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6+
desc = { enumerable: true, get: function() { return m[k]; } };
7+
}
8+
Object.defineProperty(o, k2, desc);
9+
}) : (function(o, m, k, k2) {
10+
if (k2 === undefined) k2 = k;
11+
o[k2] = m[k];
12+
}));
13+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
14+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15+
};
16+
Object.defineProperty(exports, "__esModule", { value: true });
17+
__exportStar(require("./types/enum"), exports);
18+
__exportStar(require("./types/pipe"), exports);
19+
__exportStar(require("./types/message"), exports);
20+
__exportStar(require("./plumbing"), exports);

bin/esm/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from "./types/enum";
2+
export * from "./types/pipe";
3+
export * from "./types/message";
4+
export * from "./plumbing";

bin/types/index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from "./types/enum";
2+
export * from "./types/pipe";
3+
export * from "./types/message";
4+
export * from "./plumbing";

src/test/Junction.spec.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { Pipe, PipeListener, Junction } from "../plumbing";
2+
import {
3+
IPipeFitting,
4+
IPipeMessage,
5+
PipeMessageType,
6+
JunctionType,
7+
} from "../index";
8+
9+
describe("Junction Test", () => {
10+
test("Register, retrieve and remove INPUT pipe", () => {
11+
const pipe: IPipeFitting = new Pipe();
12+
const junction = new Junction();
13+
14+
const registered = junction.registerPipe({
15+
name: "testInputPipe",
16+
type: JunctionType.INPUT,
17+
pipe,
18+
});
19+
20+
expect(pipe).toBeInstanceOf(Pipe);
21+
expect(junction).toBeInstanceOf(Junction);
22+
expect(registered).toBe(true);
23+
24+
expect(junction.hasPipe("testInputPipe")).toBe(true);
25+
expect(junction.hasInputPipe("testInputPipe")).toBe(true);
26+
expect(junction.retrievePipe("testInputPipe")).toBe(pipe);
27+
28+
junction.removePipe("testInputPipe");
29+
expect(junction.hasPipe("testInputPipe")).toBe(false);
30+
expect(junction.hasInputPipe("testInputPipe")).toBe(false);
31+
expect(junction.retrievePipe("testInputPipe")).toBeUndefined();
32+
});
33+
34+
test("Register, retrieve and remove OUTPUT pipe", () => {
35+
const pipe: IPipeFitting = new Pipe();
36+
const junction = new Junction();
37+
38+
const registered = junction.registerPipe({
39+
name: "testOutputPipe",
40+
type: JunctionType.OUTPUT,
41+
pipe,
42+
});
43+
44+
expect(pipe).toBeInstanceOf(Pipe);
45+
expect(junction).toBeInstanceOf(Junction);
46+
expect(registered).toBe(true);
47+
48+
expect(junction.hasPipe("testOutputPipe")).toBe(true);
49+
expect(junction.hasOutputPipe("testOutputPipe")).toBe(true);
50+
expect(junction.retrievePipe("testOutputPipe")).toBe(pipe);
51+
52+
junction.removePipe("testOutputPipe");
53+
expect(junction.hasPipe("testOutputPipe")).toBe(false);
54+
expect(junction.hasOutputPipe("testOutputPipe")).toBe(false);
55+
expect(junction.retrievePipe("testOutputPipe")).toBeUndefined();
56+
});
57+
58+
test("Add PipeListener to INPUT pipe and receive message", () => {
59+
const pipe: IPipeFitting = new Pipe();
60+
const junction = new Junction();
61+
const messagesReceived: IPipeMessage[] = [];
62+
const message: IPipeMessage = {
63+
type: PipeMessageType.NORMAL,
64+
header: { testVal: 1 },
65+
};
66+
67+
const registered = junction.registerPipe({
68+
name: "testInputPipe",
69+
type: JunctionType.INPUT,
70+
pipe,
71+
});
72+
73+
const listenerAdded = junction.addPipeListener("testInputPipe", (m) => {
74+
messagesReceived.push(m);
75+
});
76+
77+
const sent = pipe.write(message);
78+
79+
expect(pipe).toBeInstanceOf(Pipe);
80+
expect(junction).toBeInstanceOf(Junction);
81+
expect(registered).toBe(true);
82+
expect(listenerAdded).toBe(true);
83+
expect(sent).toBe(true);
84+
expect(messagesReceived.length).toBe(1);
85+
expect(messagesReceived.pop()).toBe(message);
86+
});
87+
88+
test("Send message on OUTPUT pipe via Junction", () => {
89+
const pipe: IPipeFitting = new Pipe();
90+
const messagesReceived: IPipeMessage[] = [];
91+
const listenerAdded = pipe.connect(
92+
new PipeListener((m) => messagesReceived.push(m)),
93+
);
94+
95+
const junction = new Junction();
96+
const message: IPipeMessage = {
97+
type: PipeMessageType.NORMAL,
98+
header: { testVal: 1 },
99+
};
100+
101+
const registered = junction.registerPipe({
102+
name: "testOutputPipe",
103+
type: JunctionType.OUTPUT,
104+
pipe,
105+
});
106+
107+
const sent = junction.sendMessage("testOutputPipe", message);
108+
109+
expect(pipe).toBeInstanceOf(Pipe);
110+
expect(junction).toBeInstanceOf(Junction);
111+
expect(registered).toBe(true);
112+
expect(listenerAdded).toBe(true);
113+
expect(sent).toBe(true);
114+
expect(messagesReceived.length).toBe(1);
115+
expect(messagesReceived.pop()).toBe(message);
116+
});
117+
});

src/test/Message.spec.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { IPipeMessage } from "../types/message";
2+
import { PipeMessageType } from "../types/enum";
3+
4+
/**
5+
* Test the Message shape (IPipeMessage).
6+
*/
7+
describe("Message Test", () => {
8+
test("Constructor shape and property access", () => {
9+
// create a message with complete fields
10+
const message: IPipeMessage = {
11+
type: PipeMessageType.NORMAL,
12+
header: { testProp: "testval" },
13+
body: { testAtt: "Hello" },
14+
priority: 1,
15+
};
16+
17+
// assertions
18+
expect(message.type).toBe(PipeMessageType.NORMAL);
19+
expect((message.header as any).testProp).toBe("testval");
20+
expect((message.body as any).testAtt).toBe("Hello");
21+
expect(message.priority).toBe(1);
22+
});
23+
24+
test("Default (omitted) priority is undefined", () => {
25+
// Create a message with minimum fields
26+
const message: IPipeMessage = { type: PipeMessageType.NORMAL };
27+
28+
// priority should be undefined unless set
29+
expect(message.priority).toBeUndefined();
30+
});
31+
32+
test("Mutating fields behaves like setters/getters", () => {
33+
// create a minimal message
34+
const message: IPipeMessage = { type: PipeMessageType.NORMAL };
35+
36+
// mutate remaining fields (analogous to setters)
37+
message.header = { testProp: "testval" } as any;
38+
message.body = { testAtt: "Hello" } as any;
39+
message.priority = 3;
40+
41+
// assertions
42+
expect(message.type).toBe(PipeMessageType.NORMAL);
43+
expect((message.header as any).testProp).toBe("testval");
44+
expect((message.body as any).testAtt).toBe("Hello");
45+
expect(message.priority).toBe(3);
46+
});
47+
});

src/test/PipeListener.spec.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { Pipe, PipeListener } from "../plumbing";
2+
import { IPipeFitting, IPipeMessage, PipeMessageType } from "../index";
3+
4+
/**
5+
* Test the PipeListener class.
6+
*/
7+
describe("PipeListener Test", () => {
8+
test("PipeListener.connect returns false and disconnect returns undefined", () => {
9+
const listener: PipeListener = new PipeListener(() => void 0);
10+
const connected = listener.connect(new Pipe());
11+
expect(connected).toBe(false);
12+
expect(listener.disconnect()).toBeUndefined();
13+
});
14+
15+
test("Connect a PipeListener to a Pipe", () => {
16+
// create pipe and listener
17+
const pipe: IPipeFitting = new Pipe();
18+
const listener: PipeListener = new PipeListener(() => void 0);
19+
20+
// connect the listener to the pipe
21+
const success: boolean = pipe.connect(listener);
22+
23+
// test assertions
24+
expect(pipe).toBeInstanceOf(Pipe);
25+
expect(success).toBe(true);
26+
});
27+
28+
test("Receive a message via PipeListener", () => {
29+
let messageReceived: IPipeMessage | undefined;
30+
31+
// create a message
32+
const messageToSend: IPipeMessage = {
33+
type: PipeMessageType.NORMAL,
34+
header: { testProp: "testval" },
35+
body: { testAtt: "Hello" },
36+
priority: 0,
37+
};
38+
39+
// create pipe and listener
40+
const pipe: IPipeFitting = new Pipe();
41+
const listener: PipeListener = new PipeListener((msg) => {
42+
messageReceived = msg;
43+
});
44+
45+
// connect the listener to the pipe and write the message
46+
const connected: boolean = pipe.connect(listener);
47+
const written: boolean = pipe.write(messageToSend);
48+
49+
// test assertions
50+
expect(pipe).toBeInstanceOf(Pipe);
51+
expect(connected).toBe(true);
52+
expect(written).toBe(true);
53+
expect(messageReceived).toBeDefined();
54+
expect((messageReceived as IPipeMessage).type).toBe(PipeMessageType.NORMAL);
55+
expect(((messageReceived as IPipeMessage).header as any).testProp).toBe(
56+
"testval",
57+
);
58+
expect(((messageReceived as IPipeMessage).body as any).testAtt).toBe(
59+
"Hello",
60+
);
61+
expect((messageReceived as IPipeMessage).priority).toBe(0);
62+
});
63+
64+
test("Write returns false when callback is undefined", () => {
65+
// Force an undefined callback using a cast
66+
const listener = new PipeListener((() => void 0) as any) as any;
67+
listener.callback = undefined;
68+
69+
const success = (listener as PipeListener).write({
70+
type: PipeMessageType.NORMAL,
71+
});
72+
expect(success).toBe(false);
73+
});
74+
});

src/test/Queue.spec.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { Pipe, Queue, PipeListener } from "../plumbing";
2+
import {
3+
IPipeFitting,
4+
IPipeMessage,
5+
PipeMessageType,
6+
QueueControlMessageType,
7+
} from "../index";
8+
9+
describe("Queue Test", () => {
10+
test("Connect input and output pipes to a Queue", () => {
11+
const pipe1: IPipeFitting = new Pipe();
12+
const pipe2: IPipeFitting = new Pipe();
13+
const queue: Queue = new Queue();
14+
15+
const connectedInput = pipe1.connect(queue);
16+
const connectedOutput = queue.connect(pipe2);
17+
18+
expect(pipe1).toBeInstanceOf(Pipe);
19+
expect(pipe2).toBeInstanceOf(Pipe);
20+
expect(queue).toBeInstanceOf(Queue);
21+
expect(connectedInput).toBe(true);
22+
expect(connectedOutput).toBe(true);
23+
});
24+
25+
test("Write multiple messages then FLUSH (FIFO)", () => {
26+
const messagesReceived: IPipeMessage[] = [];
27+
28+
const message1: IPipeMessage = {
29+
type: PipeMessageType.NORMAL,
30+
header: { testProp: 1 },
31+
};
32+
const message2: IPipeMessage = {
33+
type: PipeMessageType.NORMAL,
34+
header: { testProp: 2 },
35+
};
36+
const message3: IPipeMessage = {
37+
type: PipeMessageType.NORMAL,
38+
header: { testProp: 3 },
39+
};
40+
41+
const flush: IPipeMessage = { type: QueueControlMessageType.FLUSH } as any;
42+
43+
const queue: Queue = new Queue(new PipeListener((m) => messagesReceived.push(m)));
44+
45+
const message1written = queue.write(message1);
46+
const message2written = queue.write(message2);
47+
const message3written = queue.write(message3);
48+
49+
expect(message1written).toBe(true);
50+
expect(message2written).toBe(true);
51+
expect(message3written).toBe(true);
52+
53+
// nothing received yet (enqueued)
54+
expect(messagesReceived.length).toBe(0);
55+
56+
const flushWritten = queue.write(flush);
57+
expect(flushWritten).toBe(true);
58+
59+
// all 3 received FIFO and identity preserved
60+
expect(messagesReceived.length).toBe(3);
61+
const received1 = messagesReceived.shift() as IPipeMessage;
62+
const received2 = messagesReceived.shift() as IPipeMessage;
63+
const received3 = messagesReceived.shift() as IPipeMessage;
64+
expect(received1).toBe(message1);
65+
expect(received2).toBe(message2);
66+
expect(received3).toBe(message3);
67+
});
68+
69+
test("SORT by priority then FIFO switch", () => {
70+
const messagesReceived: IPipeMessage[] = [];
71+
72+
const message1: IPipeMessage = {
73+
type: PipeMessageType.NORMAL,
74+
priority: 2, // MEDIUM
75+
};
76+
const message2: IPipeMessage = {
77+
type: PipeMessageType.NORMAL,
78+
priority: 3, // LOW
79+
};
80+
const message3: IPipeMessage = {
81+
type: PipeMessageType.NORMAL,
82+
priority: 1, // HIGH
83+
};
84+
85+
const queue: Queue = new Queue(new PipeListener((m) => messagesReceived.push(m)));
86+
87+
// begin sort-by-priority mode
88+
const sortWritten = queue.write({ type: QueueControlMessageType.SORT } as any);
89+
90+
// write messages and flush
91+
const w1 = queue.write(message1);
92+
const w2 = queue.write(message2);
93+
const w3 = queue.write(message3);
94+
const flushWritten = queue.write({ type: QueueControlMessageType.FLUSH } as any);
95+
96+
expect(sortWritten).toBe(true);
97+
expect(w1 && w2 && w3 && flushWritten).toBe(true);
98+
expect(messagesReceived.length).toBe(3);
99+
100+
const r1 = messagesReceived.shift() as IPipeMessage;
101+
const r2 = messagesReceived.shift() as IPipeMessage;
102+
const r3 = messagesReceived.shift() as IPipeMessage;
103+
104+
// ascending numeric priority: 1 (HIGH), 2 (MED), 3 (LOW)
105+
expect((r1.priority as number) < (r2.priority as number)).toBe(true);
106+
expect((r2.priority as number) < (r3.priority as number)).toBe(true);
107+
expect(r1).toBe(message3);
108+
expect(r2).toBe(message1);
109+
expect(r3).toBe(message2);
110+
111+
// switch back to FIFO
112+
const fifoWritten = queue.write({ type: QueueControlMessageType.FIFO } as any);
113+
const w1b = queue.write(message1);
114+
const w2b = queue.write(message2);
115+
const w3b = queue.write(message3);
116+
const flushWrittenB = queue.write({ type: QueueControlMessageType.FLUSH } as any);
117+
118+
expect(fifoWritten && w1b && w2b && w3b && flushWrittenB).toBe(true);
119+
expect(messagesReceived.length).toBe(3);
120+
const rb1 = messagesReceived.shift() as IPipeMessage;
121+
const rb2 = messagesReceived.shift() as IPipeMessage;
122+
const rb3 = messagesReceived.shift() as IPipeMessage;
123+
expect(rb1).toBe(message1);
124+
expect(rb2).toBe(message2);
125+
expect(rb3).toBe(message3);
126+
});
127+
});

0 commit comments

Comments
 (0)