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. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { TerminalDependencies } from "./terminal";
import { Terminal } from "./terminal"; import { Terminal } from "./terminal";
import type { TabId } from "../dock/store"; import type { TabId } from "../dock/store";
import type { TerminalApi } from "../../../api/terminal-api"; 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; export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal;
const createTerminalInjectable = getInjectable({ const createTerminalInjectable = getInjectable({
id: "create-terminal", 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; 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 debounce from "lodash/debounce";
import type { IComputedValue } from "mobx";
import { reaction } from "mobx"; import { reaction } from "mobx";
import { Terminal as XTerm } from "xterm"; import { Terminal as XTerm } from "xterm";
import { FitAddon } from "xterm-addon-fit"; import { FitAddon } from "xterm-addon-fit";
@ -14,41 +15,36 @@ import { ThemeStore } from "../../../theme.store";
import { disposer } from "../../../utils"; import { disposer } from "../../../utils";
import { isMac } from "../../../../common/vars"; import { isMac } from "../../../../common/vars";
import { once } from "lodash"; import { once } from "lodash";
import { UserStore } from "../../../../common/user-store";
import { clipboard } from "electron"; import { clipboard } from "electron";
import logger from "../../../../common/logger"; import logger from "../../../../common/logger";
import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers"; import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers";
import assert from "assert"; 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 { export class Terminal {
private terminalConfig: TerminalConfig = UserStore.getInstance().terminalConfig; private readonly xterm: XTerm;
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 fitAddon = new FitAddon(); private readonly fitAddon = new FitAddon();
private scrollPos = 0; 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 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.xterm.element!; return this.xterm.element!;
} }
get viewport() { private get viewport() {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.elem.querySelector(".xterm-viewport")!; return this.elem.querySelector(".xterm-viewport")!;
} }
@ -63,15 +59,25 @@ export class Terminal {
const { elem } = this; const { elem } = this;
if (elem) { 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 // enable terminal addons
this.xterm.loadAddon(this.fitAddon); 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.registerLinkMatcher(/https?:\/\/[^\s]+/i, this.onClickLink);
this.xterm.attachCustomKeyEventHandler(this.keyHandler); this.xterm.attachCustomKeyEventHandler(this.keyHandler);
this.xterm.onSelectionChange(this.onSelectionChange); this.xterm.onSelectionChange(this.onSelectionChange);
@ -93,10 +99,10 @@ export class Terminal {
}, { }, {
fireImmediately: true, fireImmediately: true,
}), }),
reaction(() => UserStore.getInstance().terminalConfig.fontSize, this.setFontSize, { reaction(() => this.dependencies.terminalConfig.get().fontSize, this.setFontSize, {
fireImmediately: true, fireImmediately: true,
}), }),
reaction(() => UserStore.getInstance().terminalConfig.fontFamily, this.setFontFamily, { reaction(() => this.dependencies.terminalConfig.get().fontFamily, this.setFontFamily, {
fireImmediately: true, fireImmediately: true,
}), }),
() => onDataHandler.dispose(), () => onDataHandler.dispose(),
@ -173,7 +179,7 @@ export class Terminal {
onContextMenu = () => { onContextMenu = () => {
if ( if (
// don't paste if user hasn't turned on the feature // 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 // don't paste if the clipboard doesn't have text
&& clipboard.availableFormats().includes("text/plain") && clipboard.availableFormats().includes("text/plain")
@ -185,7 +191,7 @@ export class Terminal {
onSelectionChange = () => { onSelectionChange = () => {
const selection = this.xterm.getSelection().trim(); const selection = this.xterm.getSelection().trim();
if (UserStore.getInstance().terminalCopyOnSelect && selection) { if (this.dependencies.terminalCopyOnSelect.get() && selection) {
clipboard.writeText(selection); clipboard.writeText(selection);
} }
}; };

View File

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

View File

@ -3,15 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import React from "react"; import React from "react";
import type { RenderResult } from "@testing-library/react";
import type { import { render as testingLibraryRender } from "@testing-library/react";
RenderResult } from "@testing-library/react";
import {
render as testingLibraryRender,
} from "@testing-library/react";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import { DiContextProvider } from "@ogre-tools/injectable-react"; import { DiContextProvider } from "@ogre-tools/injectable-react";
export type DiRender = (ui: React.ReactElement) => RenderResult; 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 joinPathsInjectable from "../common/path/join-paths.injectable";
import { joinPathsFake } from "../common/test-utils/join-paths-fake"; import { joinPathsFake } from "../common/test-utils/join-paths-fake";
import hotbarStoreInjectable from "../common/hotbar-store.injectable"; import hotbarStoreInjectable from "../common/hotbar-store.injectable";
import terminalSpawningPoolInjectable from "./components/dock/terminal/terminal-spawning-pool.injectable";
export const getDiForUnitTesting = ( export const getDiForUnitTesting = (
{ doGeneralOverrides } = { doGeneralOverrides: false }, { doGeneralOverrides } = { doGeneralOverrides: false },
@ -57,6 +58,8 @@ export const getDiForUnitTesting = (
di.override(isWindowsInjectable, () => false); di.override(isWindowsInjectable, () => false);
di.override(isLinuxInjectable, () => false); di.override(isLinuxInjectable, () => false);
di.override(terminalSpawningPoolInjectable, () => new HTMLElement());
di.override(getAbsolutePathInjectable, () => getAbsolutePathFake); di.override(getAbsolutePathInjectable, () => getAbsolutePathFake);
di.override(joinPathsInjectable, () => joinPathsFake); di.override(joinPathsInjectable, () => joinPathsFake);