1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-04-07 14:38:51 -04:00
parent 488db8cab5
commit 4bf4089346
8 changed files with 113 additions and 47 deletions

View File

@ -0,0 +1,19 @@
/**
* 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";
import { computed } from "mobx";
import { toJS } from "../utils";
import userStoreInjectable from "./user-store.injectable";
const terminalConfigInjectable = getInjectable({
id: "terminal-config",
instantiate: (di) => {
const store = di.inject(userStoreInjectable);
return computed(() => toJS(store.terminalConfig));
},
});
export default terminalConfigInjectable;

View File

@ -0,0 +1,18 @@
/**
* 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";
import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable";
const terminalCopyOnSelectInjectable = getInjectable({
id: "terminal-copy-on-select",
instantiate: (di) => {
const store = di.inject(userStoreInjectable);
return computed(() => store.terminalCopyOnSelect);
},
});
export default terminalCopyOnSelectInjectable;

View File

@ -3,15 +3,27 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { TerminalDependencies } from "./terminal";
import { Terminal } from "./terminal";
import type { TabId } from "../dock/store";
import type { TerminalApi } from "../../../api/terminal-api";
import terminalSpawningPoolInjectable from "./terminal-spawning-pool.injectable";
import terminalConfigInjectable from "../../../../common/user-store/terminal-config.injectable";
import terminalCopyOnSelectInjectable from "../../../../common/user-store/terminal-copy-on-select.injectable";
export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal;
const createTerminalInjectable = getInjectable({
id: "create-terminal",
instantiate: (): CreateTerminal => (tabId, api) => new Terminal(tabId, api),
instantiate: (di): CreateTerminal => {
const dependencies: TerminalDependencies = {
spawningPool: di.inject(terminalSpawningPoolInjectable),
terminalConfig: di.inject(terminalConfigInjectable),
terminalCopyOnSelect: di.inject(terminalCopyOnSelectInjectable),
};
return (tabId, api) => new Terminal(dependencies, { tabId, api });
},
});
export default createTerminalInjectable;

View File

@ -0,0 +1,20 @@
/**
* 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";
import assert from "assert";
const terminalSpawningPoolInjectable = getInjectable({
id: "terminal-spawning-pool",
instantiate: () => {
const pool = document.getElementById("terminal-init");
assert(pool, "DOM MUST container #terminal-init element");
return pool;
},
causesSideEffects: true,
});
export default terminalSpawningPoolInjectable;

View File

@ -4,6 +4,7 @@
*/
import debounce from "lodash/debounce";
import type { IComputedValue } from "mobx";
import { reaction } from "mobx";
import { Terminal as XTerm } from "xterm";
import { FitAddon } from "xterm-addon-fit";
@ -14,41 +15,36 @@ import { ThemeStore } from "../../../theme.store";
import { disposer } from "../../../utils";
import { isMac } from "../../../../common/vars";
import { once } from "lodash";
import { UserStore } from "../../../../common/user-store";
import { clipboard } from "electron";
import logger from "../../../../common/logger";
import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers";
import assert from "assert";
export interface TerminalDependencies {
readonly spawningPool: HTMLElement;
readonly terminalConfig: IComputedValue<TerminalConfig>;
readonly terminalCopyOnSelect: IComputedValue<boolean>;
}
export interface TerminalArguments {
tabId: TabId;
api: TerminalApi;
}
export class Terminal {
private terminalConfig: TerminalConfig = UserStore.getInstance().terminalConfig;
public static spawningPool: HTMLElement;
static {
const pool = document.getElementById("terminal-init");
assert(pool, "FATAL: missing #terminal-init tag in DOM");
this.spawningPool = pool;
}
private xterm: XTerm = new XTerm({
cursorBlink: true,
cursorStyle: "bar",
fontSize: this.terminalConfig.fontSize,
fontFamily: this.terminalConfig.fontFamily,
});
private readonly xterm: XTerm;
private readonly fitAddon = new FitAddon();
private scrollPos = 0;
private disposer = disposer();
private readonly disposer = disposer();
public readonly tabId: TabId;
protected readonly api: TerminalApi;
get elem() {
private get elem() {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.xterm.element!;
}
get viewport() {
private get viewport() {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.elem.querySelector(".xterm-viewport")!;
}
@ -63,15 +59,25 @@ export class Terminal {
const { elem } = this;
if (elem) {
Terminal.spawningPool.appendChild(elem);
this.dependencies.spawningPool.appendChild(elem);
}
}
constructor(public tabId: TabId, protected api: TerminalApi) {
constructor(protected readonly dependencies: TerminalDependencies, { tabId, api }: TerminalArguments) {
this.tabId = tabId;
this.api = api;
const { fontSize, fontFamily } = this.dependencies.terminalConfig.get();
this.xterm = new XTerm({
cursorBlink: true,
cursorStyle: "bar",
fontSize,
fontFamily,
});
// enable terminal addons
this.xterm.loadAddon(this.fitAddon);
this.xterm.open(Terminal.spawningPool);
this.xterm.open(this.dependencies.spawningPool);
this.xterm.registerLinkMatcher(/https?:\/\/[^\s]+/i, this.onClickLink);
this.xterm.attachCustomKeyEventHandler(this.keyHandler);
this.xterm.onSelectionChange(this.onSelectionChange);
@ -93,10 +99,10 @@ export class Terminal {
}, {
fireImmediately: true,
}),
reaction(() => UserStore.getInstance().terminalConfig.fontSize, this.setFontSize, {
reaction(() => this.dependencies.terminalConfig.get().fontSize, this.setFontSize, {
fireImmediately: true,
}),
reaction(() => UserStore.getInstance().terminalConfig.fontFamily, this.setFontFamily, {
reaction(() => this.dependencies.terminalConfig.get().fontFamily, this.setFontFamily, {
fireImmediately: true,
}),
() => onDataHandler.dispose(),
@ -173,7 +179,7 @@ export class Terminal {
onContextMenu = () => {
if (
// don't paste if user hasn't turned on the feature
UserStore.getInstance().terminalCopyOnSelect
this.dependencies.terminalCopyOnSelect.get()
// don't paste if the clipboard doesn't have text
&& clipboard.availableFormats().includes("text/plain")
@ -185,7 +191,7 @@ export class Terminal {
onSelectionChange = () => {
const selection = this.xterm.getSelection().trim();
if (UserStore.getInstance().terminalCopyOnSelect && selection) {
if (this.dependencies.terminalCopyOnSelect.get() && selection) {
clipboard.writeText(selection);
}
};

View File

@ -101,9 +101,7 @@ exports[`kube-object-menu given kube object when removing kube object renders 1`
<div>
<p>
Remove
some-kind
Remove some-kind
<b>
some-namespace/some-name
</b>
@ -198,9 +196,7 @@ exports[`kube-object-menu given kube object with namespace when removing kube ob
<div>
<p>
Remove
some-kind
Remove some-kind
<b>
some-namespace/some-name
</b>
@ -295,9 +291,7 @@ exports[`kube-object-menu given kube object without namespace when removing kube
<div>
<p>
Remove
some-kind
Remove some-kind
<b>
some-name
</b>

View File

@ -3,15 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import React from "react";
import type {
RenderResult } from "@testing-library/react";
import {
render as testingLibraryRender,
} from "@testing-library/react";
import type { RenderResult } from "@testing-library/react";
import { render as testingLibraryRender } from "@testing-library/react";
import type { DiContainer } from "@ogre-tools/injectable";
import { DiContextProvider } from "@ogre-tools/injectable-react";
export type DiRender = (ui: React.ReactElement) => RenderResult;

View File

@ -33,6 +33,7 @@ import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake
import joinPathsInjectable from "../common/path/join-paths.injectable";
import { joinPathsFake } from "../common/test-utils/join-paths-fake";
import hotbarStoreInjectable from "../common/hotbar-store.injectable";
import terminalSpawningPoolInjectable from "./components/dock/terminal/terminal-spawning-pool.injectable";
export const getDiForUnitTesting = (
{ doGeneralOverrides } = { doGeneralOverrides: false },
@ -57,6 +58,8 @@ export const getDiForUnitTesting = (
di.override(isWindowsInjectable, () => false);
di.override(isLinuxInjectable, () => false);
di.override(terminalSpawningPoolInjectable, () => new HTMLElement());
di.override(getAbsolutePathInjectable, () => getAbsolutePathFake);
di.override(joinPathsInjectable, () => joinPathsFake);