1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

[EC-598] feat: add basic test-case for messenger

This commit is contained in:
Andreas Coroiu
2023-01-27 13:28:54 +01:00
parent ae15a24f58
commit 0f875b93a1
2 changed files with 87 additions and 4 deletions

View File

@@ -0,0 +1,83 @@
import { Subject } from "rxjs";
import { Utils } from "@bitwarden/common/misc/utils";
import { Message } from "./message";
import { Channel, MessageWithMetadata, Messenger } from "./messenger";
describe("Messenger", () => {
let messengerA: Messenger;
let messengerB: Messenger;
let handlerA: TestMessageHandler;
let handlerB: TestMessageHandler;
beforeEach(() => {
const channelPair = new TestChannelPair();
messengerA = new Messenger(channelPair.channelA);
messengerB = new Messenger(channelPair.channelB);
handlerA = new TestMessageHandler();
handlerB = new TestMessageHandler();
messengerA.addHandler(handlerA.handler);
messengerB.addHandler(handlerB.handler);
});
it("should deliver message to B when sending request to A", () => {
const message = createMessage();
messengerA.request(message);
const received = handlerB.recieve();
expect(received.length).toBe(1);
expect(received[0].message).toMatchObject(message);
});
});
type TestMessage = Message & { testId: string };
function createMessage(): TestMessage {
return { testId: Utils.newGuid(), type: "TestMessage" } as any;
}
class TestChannelPair {
readonly channelA: Channel;
readonly channelB: Channel;
constructor() {
const subjectA = new Subject<MessageWithMetadata>();
const subjectB = new Subject<MessageWithMetadata>();
this.channelA = {
messages$: subjectA,
postMessage: (message) => subjectB.next(message),
};
this.channelB = {
messages$: subjectB,
postMessage: (message) => subjectB.next(message),
};
}
}
class TestMessageHandler {
readonly handler: (message: TestMessage) => Promise<Message | undefined>;
private recievedMessages: { message: TestMessage; respond: (response: TestMessage) => void }[] =
[];
constructor() {
this.handler = (message) =>
new Promise((resolve, reject) => {
this.recievedMessages.push({
message,
respond: (response) => resolve(response),
});
});
}
recieve() {
const received = this.recievedMessages;
this.recievedMessages = [];
return received;
}
}

View File

@@ -4,13 +4,13 @@ import { Message } from "./message";
type PostMessageFunction = (message: MessageWithMetadata) => void; type PostMessageFunction = (message: MessageWithMetadata) => void;
type Channel = { export type Channel = {
messages$: Observable<MessageWithMetadata>; messages$: Observable<MessageWithMetadata>;
postMessage: PostMessageFunction; postMessage: PostMessageFunction;
}; };
type Metadata = { requestId: string }; export type Metadata = { requestId: string };
type MessageWithMetadata = Message & { metadata: Metadata }; export type MessageWithMetadata = Message & { metadata: Metadata };
// TODO: This class probably duplicates functionality but I'm not especially familiar with // TODO: This class probably duplicates functionality but I'm not especially familiar with
// the inner workings of the browser extension yet. // the inner workings of the browser extension yet.
@@ -32,7 +32,7 @@ export class Messenger {
}); });
} }
private constructor(private channel: Channel) {} constructor(private channel: Channel) {}
request(request: Message): Promise<Message> { request(request: Message): Promise<Message> {
const requestId = Date.now().toString(); const requestId = Date.now().toString();