From 1b700491f9c42883891610aec5dc770e094d5074 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Wed, 6 Jul 2022 11:39:57 -0400 Subject: [PATCH] Add more injectables Signed-off-by: Sebastian Malton --- .../api/create-terminal-api.injectable.ts | 6 ++++ .../api/create-websocket.injectable.ts | 14 +++++++++ .../default-websocket-params.injectable.ts | 22 ++++++++++++++ src/renderer/api/terminal-api.ts | 6 ++-- src/renderer/api/websocket-api.ts | 24 +++++++-------- src/techincal/shell-sessions/local.test.ts | 29 +------------------ 6 files changed, 57 insertions(+), 44 deletions(-) create mode 100644 src/renderer/api/create-websocket.injectable.ts create mode 100644 src/renderer/api/default-websocket-params.injectable.ts diff --git a/src/renderer/api/create-terminal-api.injectable.ts b/src/renderer/api/create-terminal-api.injectable.ts index 80b1727d0b..7afe103625 100644 --- a/src/renderer/api/create-terminal-api.injectable.ts +++ b/src/renderer/api/create-terminal-api.injectable.ts @@ -8,6 +8,8 @@ import hostedClusterIdInjectable from "../cluster-frame-context/hosted-cluster-i import getShellAuthTokenInjectable from "../../common/shell-authentication/get-auth-token.injectable"; import type { TerminalApiQuery } from "./terminal-api"; import { TerminalApi } from "./terminal-api"; +import createWebsocketInjectable from "./create-websocket.injectable"; +import defaultWebsocketParamsInjectable from "./default-websocket-params.injectable"; export type CreateTerminalApi = (query: TerminalApiQuery) => TerminalApi; @@ -16,6 +18,8 @@ const createTerminalApiInjectable = getInjectable({ instantiate: (di): CreateTerminalApi => { const hostedClusterId = di.inject(hostedClusterIdInjectable); const getShellAuthToken = di.inject(getShellAuthTokenInjectable); + const createWebsocket = di.inject(createWebsocketInjectable); + const defaultParams = di.inject(defaultWebsocketParamsInjectable); return (query) => { assert(hostedClusterId, "Can only create terminal APIs within a cluster frame"); @@ -23,6 +27,8 @@ const createTerminalApiInjectable = getInjectable({ return new TerminalApi({ hostedClusterId, getShellAuthToken, + createWebsocket, + defaultParams, }, query); }; }, diff --git a/src/renderer/api/create-websocket.injectable.ts b/src/renderer/api/create-websocket.injectable.ts new file mode 100644 index 0000000000..4459fcac80 --- /dev/null +++ b/src/renderer/api/create-websocket.injectable.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; + +export type CreateWebsocket = (url: string) => WebSocket; + +const createWebsocketInjectable = getInjectable({ + id: "create-websocket", + instantiate: (): CreateWebsocket => (url) => new WebSocket(url), +}); + +export default createWebsocketInjectable; diff --git a/src/renderer/api/default-websocket-params.injectable.ts b/src/renderer/api/default-websocket-params.injectable.ts new file mode 100644 index 0000000000..b3fd5c2b64 --- /dev/null +++ b/src/renderer/api/default-websocket-params.injectable.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import type { Injectable } from "@ogre-tools/injectable"; +import { getInjectable } from "@ogre-tools/injectable"; +import { TerminalChannels, type TerminalMessage } from "../../common/terminal/channels"; +import isDevelopmentInjectable from "../../common/vars/is-development.injectable"; + +export type DefaultWebsocketParams = typeof defaultWebsocketParamsInjectable extends Injectable ? T : never; + +const defaultWebsocketParamsInjectable = getInjectable({ + id: "default-websocket-params", + instantiate: (di) => ({ + logging: di.inject(isDevelopmentInjectable), + reconnectDelay: 10, + flushOnOpen: true, + pingMessage: JSON.stringify({ type: TerminalChannels.PING } as TerminalMessage), + }), +}); + +export default defaultWebsocketParamsInjectable; diff --git a/src/renderer/api/terminal-api.ts b/src/renderer/api/terminal-api.ts index 73acd4e218..7590c1e755 100644 --- a/src/renderer/api/terminal-api.ts +++ b/src/renderer/api/terminal-api.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import type { WebSocketEvents } from "./websocket-api"; +import type { WebSocketApiDependencies, WebSocketEvents } from "./websocket-api"; import { WebSocketApi } from "./websocket-api"; import isEqual from "lodash/isEqual"; import url from "url"; @@ -36,7 +36,7 @@ export interface TerminalEvents extends WebSocketEvents { connected: () => void; } -export interface TerminalApiDependencies { +export interface TerminalApiDependencies extends WebSocketApiDependencies { readonly hostedClusterId: string; getShellAuthToken: GetShellAuthToken; } @@ -47,7 +47,7 @@ export class TerminalApi extends WebSocketApi { @observable public isReady = false; constructor(protected readonly dependencies: TerminalApiDependencies, protected readonly query: TerminalApiQuery) { - super({ + super(dependencies, { flushOnOpen: false, pingInterval: 30, }); diff --git a/src/renderer/api/websocket-api.ts b/src/renderer/api/websocket-api.ts index 748fef5e7b..8f3a73ae78 100644 --- a/src/renderer/api/websocket-api.ts +++ b/src/renderer/api/websocket-api.ts @@ -7,9 +7,9 @@ import { observable, makeObservable } from "mobx"; import EventEmitter from "events"; import type TypedEventEmitter from "typed-emitter"; import type { Arguments } from "typed-emitter"; -import { isDevelopment } from "../../common/vars"; import type { Defaulted } from "../utils"; -import { TerminalChannels, type TerminalMessage } from "../../common/terminal/channels"; +import type { CreateWebsocket } from "./create-websocket.injectable"; +import type { DefaultWebsocketParams } from "./default-websocket-params.injectable"; interface WebsocketApiParams { /** @@ -64,27 +64,25 @@ export interface WebSocketEvents { close: () => void; } +export interface WebSocketApiDependencies { + createWebsocket: CreateWebsocket; + readonly defaultParams: DefaultWebsocketParams; +} + export class WebSocketApi extends (EventEmitter as { new(): TypedEventEmitter }) { protected socket: WebSocket | null = null; protected pendingCommands: string[] = []; protected reconnectTimer?: number; protected pingTimer?: number; - protected params: Defaulted; + protected readonly params: Defaulted; @observable readyState = WebSocketApiState.PENDING; - private static readonly defaultParams = { - logging: isDevelopment, - reconnectDelay: 10, - flushOnOpen: true, - pingMessage: JSON.stringify({ type: TerminalChannels.PING } as TerminalMessage), - }; - - constructor(params: WebsocketApiParams) { + constructor(protected readonly dependencies: WebSocketApiDependencies, params: WebsocketApiParams) { super(); makeObservable(this); this.params = { - ...WebSocketApi.defaultParams, + ...this.dependencies.defaultParams, ...params, }; const { pingInterval } = this.params; @@ -111,7 +109,7 @@ export class WebSocketApi extends (EventEmitter this.socket?.close(); // start new connection - this.socket = new WebSocket(url); + this.socket = this.dependencies.createWebsocket(url); this.socket.addEventListener("open", ev => this._onOpen(ev)); this.socket.addEventListener("message", ev => this._onMessage(ev)); this.socket.addEventListener("error", ev => this._onError(ev)); diff --git a/src/techincal/shell-sessions/local.test.ts b/src/techincal/shell-sessions/local.test.ts index a4c9109eaf..32359b4d98 100644 --- a/src/techincal/shell-sessions/local.test.ts +++ b/src/techincal/shell-sessions/local.test.ts @@ -4,43 +4,21 @@ */ import type { RenderResult } from "@testing-library/react"; -import { waitFor } from "@testing-library/react"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import getShellAuthTokenChannelHandlerInjectable from "../../main/lens-proxy/proxy-functions/shell/auth-token-channel-handler.injectable"; import type { GetShellAuthToken } from "../../common/shell-authentication/get-auth-token.injectable"; -import type { SpawnPty } from "../../main/shell-session/spawn-pty.injectable"; import spawnPtyInjectable from "../../main/shell-session/spawn-pty.injectable"; -import type { IPty } from "node-pty"; describe("local shell session techincal tests", () => { let builder: ApplicationBuilder; let result: RenderResult; let authenticationSpy: jest.SpyInstance, Parameters>; - let spawnPtyMock: jest.MockedFunction; - let ptyMock: jest.MockedObject; beforeEach(async () => { builder = getApplicationBuilder() .beforeApplicationStart(() => { - spawnPtyMock = jest.fn(); - builder.dis.mainDi.override(spawnPtyInjectable, () => spawnPtyMock); - - spawnPtyMock.mockImplementation(() => ptyMock = { - cols: 80, - rows: 40, - pid: 12346, - process: "my-mocked-shell", - handleFlowControl: true, - kill: jest.fn(), - onData: jest.fn(), - onExit: jest.fn(), - on: jest.fn(), - resize: jest.fn(), - write: jest.fn(), - pause: jest.fn(), - resume: jest.fn(), - }); + builder.dis.mainDi.override(spawnPtyInjectable, () => jest.fn()); }) .beforeRender(() => { const shellAuthentication = builder.dis.mainDi.inject(getShellAuthTokenChannelHandlerInjectable); @@ -60,9 +38,4 @@ describe("local shell session techincal tests", () => { it("should call the authentication function", () => { expect(authenticationSpy).toBeCalled(); }); - - it("should create a pty instance", async () => { - await waitFor(() => expect(spawnPtyMock).toBeCalled()); - void ptyMock; - }); });