-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: (wip) websocket server duplex connectio tests
Signed-off-by: Kevin Viglucci <[email protected]>
- Loading branch information
Showing
2 changed files
with
341 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
321 changes: 321 additions & 0 deletions
321
packages/rsocket-websocket-server/src/__tests__/WebsocketDuplexConnection.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
// }); | ||
// }); | ||
// }); | ||
}); |