Skip to content

Commit

Permalink
test: (wip) websocket server duplex connectio tests
Browse files Browse the repository at this point in the history
Signed-off-by: Kevin Viglucci <[email protected]>
  • Loading branch information
viglucci committed Jun 14, 2024
1 parent 4a08254 commit 1f3ab7a
Show file tree
Hide file tree
Showing 2 changed files with 341 additions and 0 deletions.
20 changes: 20 additions & 0 deletions packages/rsocket-websocket-server/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Config } from "@jest/types";
import { pathsToModuleNameMapper } from "ts-jest/utils";
import { compilerOptions } from "../../tsconfig.json";

const config: Config.InitialOptions = {
preset: "ts-jest",
testRegex: "(\\/__tests__\\/.*|\\.(test|spec))\\.(ts)$",
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
// This has to match the baseUrl defined in tsconfig.json.
prefix: "<rootDir>/../../",
}),
modulePathIgnorePatterns: [
"<rootDir>/__tests__/test-utils",
"<rootDir>/__tests__/*.d.ts",
],
collectCoverage: true,
collectCoverageFrom: ["<rootDir>/src/**/*.ts", "!**/node_modules/**"],
};

export default config;
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
import { mock } from "jest-mock-extended";
import {
Demultiplexer,
Deserializer,
Flags,
Frame,
FrameHandler,
FrameTypes,
Multiplexer,
serializeFrame,
SetupFrame,
} from "rsocket-core";
import { WebsocketDuplexConnection } from "../WebsocketDuplexConnection";
// import { MockSocket } from "../__mocks__/ws";
import { Duplex } from "stream";

// const deserializer = mock<Deserializer>();

describe("WebsocketDuplexConnection", function () {
describe("when closed", () => {
it("removes listeners from the underlying socket event emitter", () => {
// arrange
const socketStub = mock<Duplex>();
const multiplexerDemultiplexer = mock<
Multiplexer & Demultiplexer & FrameHandler
>();
const frame = mock<Frame>();
const connection = new WebsocketDuplexConnection(
socketStub,
frame,
() => multiplexerDemultiplexer
);

// act
connection.close();

// assert
expect(socketStub.removeAllListeners).toBeCalledWith();
});

it("cleans up the socket resource when closed without an error", () => {
// arrange
const socketStub = mock<Duplex>();
const multiplexerDemultiplexer = mock<
Multiplexer & Demultiplexer & FrameHandler
>();
const frame = mock<Frame>();
const connection = new WebsocketDuplexConnection(
socketStub,
frame,
() => multiplexerDemultiplexer
);

// act
connection.close();

// assert
expect(socketStub.end).toBeCalledWith();
});

it("cleans up the socket resource when closed with an error", () => {
// arrange
const socketStub = mock<Duplex>();
const multiplexerDemultiplexer = mock<
Multiplexer & Demultiplexer & FrameHandler
>();
const frame = mock<Frame>();
const connection = new WebsocketDuplexConnection(
socketStub,
frame,
() => multiplexerDemultiplexer
);

// act
const error = new Error();
connection.close(error);

// assert
expect(socketStub.end).toBeCalledWith();
});

it("calls the onClose callback when one is registered", () => {
// arrange
const socketStub = mock<Duplex>();
const multiplexerDemultiplexer = mock<
Multiplexer & Demultiplexer & FrameHandler
>();
const frame = mock<Frame>();
const connection = new WebsocketDuplexConnection(
socketStub,
frame,
() => multiplexerDemultiplexer
);
const onCloseCallback = jest.fn();

// act
connection.onClose(onCloseCallback);
connection.close();

// assert
expect(onCloseCallback).toBeCalledTimes(1);
expect(onCloseCallback).toBeCalledWith();
});

it("when closed with an error it calls the onClose callback when one is registered", () => {
// arrange
const socketStub = mock<Duplex>();
const multiplexerDemultiplexer = mock<
Multiplexer & Demultiplexer & FrameHandler
>();
const frame = mock<Frame>();
const connection = new WebsocketDuplexConnection(
socketStub,
frame,
() => multiplexerDemultiplexer
);
const onCloseCallback = jest.fn();
const error = new Error();

// act
connection.onClose(onCloseCallback);
connection.close(error);

// assert
expect(onCloseCallback).toBeCalledTimes(1);
expect(onCloseCallback).toBeCalledWith(error);
});
//
// it("subsequent calls to close result in only a single invocation of onClose", () => {
// const socketStub = mock<WebSocket>();
// const multiplexerDemultiplexer = mock<
// Multiplexer & Demultiplexer & FrameHandler
// >();
// const connection = new WebsocketDuplexConnection(
// socketStub,
// deserializer,
// () => multiplexerDemultiplexer
// );
// const onCloseCallback = jest.fn();
// const error = new Error();
// connection.onClose(onCloseCallback);
// connection.close(error);
// connection.close(error);
//
// expect(onCloseCallback).toBeCalledTimes(1);
// expect(onCloseCallback).toBeCalledWith(error);
// });
//
// it("the onClose callback is called with an error when the socket is closed unexpectedly", () => {
// const socket = new MockSocket() as unknown as WebSocket;
// const multiplexerDemultiplexer = mock<
// Multiplexer & Demultiplexer & FrameHandler
// >();
// const connection = new WebsocketDuplexConnection(
// socket,
// deserializer,
// () => multiplexerDemultiplexer
// );
// const onCloseCallback = jest.fn();
//
// connection.onClose(onCloseCallback);
// (socket as unknown as MockSocket).mock.close({});
//
// expect(onCloseCallback).toBeCalledTimes(1);
// expect(onCloseCallback).toHaveBeenCalledWith(
// new Error("WebsocketDuplexConnection: Socket closed unexpectedly.")
// );
// });
//
// it("the onClose callback is called with an error when the socket is closed with an error", () => {
// const socket = new MockSocket() as unknown as WebSocket;
// const multiplexerDemultiplexer = mock<
// Multiplexer & Demultiplexer & FrameHandler
// >();
// const connection = new WebsocketDuplexConnection(
// socket,
// deserializer,
// () => multiplexerDemultiplexer
// );
// const onCloseCallback = jest.fn();
// const expectedError = new Error(
// "WebsocketDuplexConnection: Test error 1"
// );
//
// connection.onClose(onCloseCallback);
// (socket as unknown as MockSocket).mock.error({ error: expectedError });
//
// expect(onCloseCallback).toBeCalledTimes(1);
// expect(onCloseCallback).toHaveBeenCalledWith(expectedError);
// });
});

// describe("send()", () => {
// const setupFrame = {
// type: FrameTypes.SETUP,
// dataMimeType: "application/octet-stream",
// metadataMimeType: "application/octet-stream",
// keepAlive: 60000,
// lifetime: 300000,
// metadata: Buffer.from("hello world"),
// data: Buffer.from("hello world"),
// resumeToken: null,
// streamId: 0,
// majorVersion: 1,
// minorVersion: 0,
// flags: Flags.METADATA,
// } as SetupFrame;
//
// it("serializes and writes the given frame to the underlying socket", () => {
// // arrange
// const socketStub = mock<WebSocket>();
// const multiplexerDemultiplexer = mock<
// Multiplexer & Demultiplexer & FrameHandler
// >();
// const connection = new WebsocketDuplexConnection(
// socketStub,
// deserializer,
// () => multiplexerDemultiplexer
// );
//
// // act
// connection.send(setupFrame);
//
// // assert
// expect(socketStub.send).toBeCalledWith(expect.any(Buffer));
// });
//
// it("does not write the given frame to the underlying socket when close was previously called", () => {
// // arrange
// const socketStub = mock<WebSocket>();
// const multiplexerDemultiplexer = mock<
// Multiplexer & Demultiplexer & FrameHandler
// >();
// const connection = new WebsocketDuplexConnection(
// socketStub,
// deserializer,
// () => multiplexerDemultiplexer
// );
//
// // act
// connection.close();
// connection.send(setupFrame);
//
// // assert
// expect(socketStub.send).toBeCalledTimes(0);
// });
// });
//
// describe("when receiving data", () => {
// const setupFrame: SetupFrame = {
// type: FrameTypes.SETUP,
// dataMimeType: "application/octet-stream",
// metadataMimeType: "application/octet-stream",
// keepAlive: 60000,
// lifetime: 300000,
// metadata: Buffer.from("hello world"),
// data: Buffer.from("hello world"),
// resumeToken: null,
// streamId: 0,
// majorVersion: 1,
// minorVersion: 0,
// flags: Flags.METADATA,
// };
//
// describe("when buffer contains a single frame", () => {
// it("deserializes received frames and calls the configured handler", () => {
// // arrange
// const multiplexerDemultiplexer = mock<
// Multiplexer & Demultiplexer & FrameHandler
// >();
// const socketStub = new MockSocket() as unknown as WebSocket;
// const connection = new WebsocketDuplexConnection(
// socketStub,
// new Deserializer(),
// () => multiplexerDemultiplexer
// );
//
// // act
// (socketStub as unknown as MockSocket).mock.message({
// data: serializeFrame(setupFrame),
// });
//
// // assert
// expect(multiplexerDemultiplexer.handle).toBeCalledTimes(1);
//
// const [call0] = multiplexerDemultiplexer.handle.mock.calls;
// const [arg0] = call0;
// expect(arg0).toMatchSnapshot();
// });
// });
//
// describe("causes an error", () => {
// it("the connection is closed", () => {
// // arrange
// const multiplexerDemultiplexer = mock<
// Multiplexer & Demultiplexer & FrameHandler
// >();
// const socketStub = new MockSocket() as unknown as WebSocket;
// const deserializerStub = mock<Deserializer>();
// const connection = new WebsocketDuplexConnection(
// socketStub as unknown as WebSocket,
// deserializerStub,
// () => multiplexerDemultiplexer
// );
// deserializerStub.deserializeFrame.mockImplementation(() => {
// throw new Error("Mock error");
// });
// const onCloseCallback = jest.fn();
// const data = Buffer.allocUnsafe(0).toString();
//
// // act
// connection.onClose(onCloseCallback);
// (socketStub as unknown as MockSocket).mock.message({ data });
//
// // assert
// expect(onCloseCallback).toBeCalledTimes(1);
// expect(onCloseCallback).toBeCalledWith(expect.any(Error));
// });
// });
// });
});

0 comments on commit 1f3ab7a

Please sign in to comment.