diff --git a/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts b/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts
index c58152716f..8961ea8424 100644
--- a/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts
+++ b/src/extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications.ts
@@ -33,7 +33,7 @@ export const asLegacyGlobalObjectForExtensionApiWithModifications = <
...instantiationParameter,
);
- const propertyValue = instance[propertyName] ?? otherFields[propertyName as any];
+ const propertyValue = instance[propertyName] ?? otherFields[propertyName as any]();
if (typeof propertyValue === "function") {
return function (...args: any[]) {
diff --git a/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx b/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx
index 762e915a63..28ed8a8563 100644
--- a/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx
+++ b/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx
@@ -37,10 +37,6 @@ jest.mock("electron", () => ({
},
}));
-const getComponent = (model: LogTabViewModel) => (
-
-);
-
function mockLogTabViewModel(tabId: TabId, deps: Partial): LogTabViewModel {
return new LogTabViewModel(tabId, {
getLogs: jest.fn(),
@@ -54,6 +50,7 @@ function mockLogTabViewModel(tabId: TabId, deps: Partial", () => {
it("renders w/o errors", () => {
const model = getOnePodViewModel("foobar");
- const { container } = render(getComponent(model));
+ const { container } = render();
expect(container).toBeInstanceOf(HTMLElement);
});
it("renders proper namespace", async () => {
const model = getOnePodViewModel("foobar");
- const { findByTestId } = render(getComponent(model));
+ const { findByTestId } = render();
const ns = await findByTestId("namespace-badge");
expect(ns).toHaveTextContent("default");
@@ -159,7 +156,7 @@ describe("", () => {
it("renders proper selected items within dropdowns", async () => {
const model = getOnePodViewModel("foobar");
- const { findByText } = render(getComponent(model));
+ const { findByText } = render();
expect(await findByText("dockerExporter")).toBeInTheDocument();
expect(await findByText("docker-exporter")).toBeInTheDocument();
@@ -167,7 +164,7 @@ describe("", () => {
it("renders sibling pods in dropdown", async () => {
const model = getFewPodsTabData("foobar");
- const { container, findByText } = render(getComponent(model));
+ const { container, findByText } = render();
selectEvent.openMenu(container.querySelector(".pod-selector"));
expect(await findByText("deploymentPod2", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument();
@@ -176,7 +173,7 @@ describe("", () => {
it("renders sibling containers in dropdown", async () => {
const model = getFewPodsTabData("foobar");
- const { findByText, container } = render(getComponent(model));
+ const { findByText, container } = render();
selectEvent.openMenu(container.querySelector(".container-selector"));
expect(await findByText("node-exporter-1")).toBeInTheDocument();
@@ -186,7 +183,7 @@ describe("", () => {
it("renders pod owner as dropdown title", async () => {
const model = getFewPodsTabData("foobar");
- const { findByText, container } = render(getComponent(model));
+ const { findByText, container } = render();
selectEvent.openMenu(container.querySelector(".pod-selector"));
expect(await findByText("super-deployment")).toBeInTheDocument();
@@ -195,7 +192,7 @@ describe("", () => {
it("updates tab name if selected pod changes", async () => {
const updateTabName = jest.fn();
const model = getFewPodsTabData("foobar", { updateTabName });
- const { findByText, container } = render(getComponent(model));
+ const { findByText, container } = render();
selectEvent.openMenu(container.querySelector(".pod-selector"));
diff --git a/src/renderer/components/dock/logs/__test__/log-search.test.tsx b/src/renderer/components/dock/logs/__test__/log-search.test.tsx
index a72859300e..8aa75799bf 100644
--- a/src/renderer/components/dock/logs/__test__/log-search.test.tsx
+++ b/src/renderer/components/dock/logs/__test__/log-search.test.tsx
@@ -3,4 +3,101 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
-export {};
+import React from "react";
+import { screen } from "@testing-library/react";
+import { Pod } from "../../../../../common/k8s-api/endpoints";
+import { dockerPod } from "./pod.mock";
+import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
+import type { DiRender } from "../../../test-utils/renderFor";
+import { renderFor } from "../../../test-utils/renderFor";
+import { LogTabViewModel, LogTabViewModelDependencies } from "../logs-view-model";
+import type { TabId } from "../../dock/store";
+import { LogSearch } from "../search";
+import userEvent from "@testing-library/user-event";
+import { SearchStore } from "../../../../search-store/search-store";
+
+function mockLogTabViewModel(tabId: TabId, deps: Partial): LogTabViewModel {
+ return new LogTabViewModel(tabId, {
+ getLogs: jest.fn(),
+ getLogsWithoutTimestamps: jest.fn(),
+ getTimestampSplitLogs: jest.fn(),
+ getLogTabData: jest.fn(),
+ setLogTabData: jest.fn(),
+ loadLogs: jest.fn(),
+ reloadLogs: jest.fn(),
+ updateTabName: jest.fn(),
+ stopLoadingLogs: jest.fn(),
+ getPodById: jest.fn(),
+ getPodsByOwnerId: jest.fn(),
+ createSearchStore: () => new SearchStore(),
+ ...deps,
+ });
+}
+
+const getOnePodViewModel = (tabId: TabId, deps: Partial = {}): LogTabViewModel => {
+ const selectedPod = new Pod(dockerPod);
+
+ return mockLogTabViewModel(tabId, {
+ getLogTabData: () => ({
+ selectedPodId: selectedPod.getId(),
+ selectedContainer: selectedPod.getContainers()[0].name,
+ namespace: selectedPod.getNs(),
+ showPrevious: false,
+ showTimestamps: false,
+ }),
+ getPodById: (id) => {
+ if (id === selectedPod.getId()) {
+ return selectedPod;
+ }
+
+ return undefined;
+ },
+ ...deps,
+ });
+};
+
+describe("LogSearch tests", () => {
+ let render: DiRender;
+
+ beforeEach(async () => {
+ const di = getDiForUnitTesting({ doGeneralOverrides: true });
+
+ render = renderFor(di);
+
+ await di.runSetups();
+ });
+
+ it("renders w/o errors", () => {
+ const model = getOnePodViewModel("foobar");
+ const { container } = render(
+ ,
+ );
+
+ expect(container).toBeInstanceOf(HTMLElement);
+ });
+
+ it("should scroll to new active overlay when clicking the previous button", async () => {
+ const scrollToOverlay = jest.fn();
+ const model = getOnePodViewModel("foobar", {
+ getLogsWithoutTimestamps: () => [
+ "hello",
+ "world",
+ ],
+ });
+
+ render(
+ ,
+ );
+
+ userEvent.click(await screen.findByPlaceholderText("Search..."));
+ userEvent.keyboard("o");
+ userEvent.click(await screen.findByText("keyboard_arrow_up"));
+ expect(scrollToOverlay).toBeCalled();
+ });
+});
diff --git a/src/renderer/components/dock/logs/logs-view-model.injectable.ts b/src/renderer/components/dock/logs/logs-view-model.injectable.ts
index 93e2008678..71264ab129 100644
--- a/src/renderer/components/dock/logs/logs-view-model.injectable.ts
+++ b/src/renderer/components/dock/logs/logs-view-model.injectable.ts
@@ -15,6 +15,7 @@ import setLogTabDataInjectable from "./set-log-tab-data.injectable";
import updateTabNameInjectable from "./update-tab-name.injectable";
import stopLoadingLogsInjectable from "./stop-loading-logs.injectable";
import { podsStore } from "../../+workloads-pods/pods.store";
+import createSearchStoreInjectable from "../../../search-store/create-search-store.injectable";
export interface InstantiateArgs {
tabId: TabId;
@@ -33,6 +34,7 @@ const logsViewModelInjectable = getInjectable({
stopLoadingLogs: di.inject(stopLoadingLogsInjectable),
getPodById: id => podsStore.getById(id),
getPodsByOwnerId: id => podsStore.getPodsByOwnerId(id),
+ createSearchStore: di.inject(createSearchStoreInjectable),
}),
lifecycle: lifecycleEnum.transient,
});
diff --git a/src/renderer/components/dock/logs/logs-view-model.ts b/src/renderer/components/dock/logs/logs-view-model.ts
index 02185c7152..3af2ea8612 100644
--- a/src/renderer/components/dock/logs/logs-view-model.ts
+++ b/src/renderer/components/dock/logs/logs-view-model.ts
@@ -5,7 +5,7 @@
import type { LogTabData } from "./tab-store";
import { computed, IComputedValue } from "mobx";
import type { TabId } from "../dock/store";
-import { SearchStore } from "../../../search-store/search-store";
+import type { SearchStore } from "../../../search-store/search-store";
import type { Pod } from "../../../../common/k8s-api/endpoints";
export interface LogTabViewModelDependencies {
@@ -20,6 +20,7 @@ export interface LogTabViewModelDependencies {
stopLoadingLogs: (tabId: TabId) => void;
getPodById: (id: string) => Pod | undefined;
getPodsByOwnerId: (id: string) => Pod[];
+ createSearchStore: () => SearchStore;
}
export class LogTabViewModel {
@@ -51,7 +52,7 @@ export class LogTabViewModel {
return this.dependencies.getPodById(data.selectedPodId);
});
- readonly searchStore = new SearchStore();
+ readonly searchStore = this.dependencies.createSearchStore();
updateLogTabData = (partialData: Partial) => {
this.dependencies.setLogTabData(this.tabId, { ...this.logTabData.get(), ...partialData });
diff --git a/src/renderer/components/dock/terminal/send-command.injectable.ts b/src/renderer/components/dock/terminal/send-command.injectable.ts
index d4f2d16e09..5428b27ac1 100644
--- a/src/renderer/components/dock/terminal/send-command.injectable.ts
+++ b/src/renderer/components/dock/terminal/send-command.injectable.ts
@@ -41,27 +41,25 @@ async function sendCommand({ selectTab, createTerminalTab, getTerminalApi }: Dep
if (tabId) {
selectTab(tabId);
} else {
- const tab = createTerminalTab();
-
- tabId = tab.id;
- await when(() => Boolean(getTerminalApi(tab.id)));
-
- const shellIsReady = when(() => getTerminalApi(tab.id).isReady);
- const notifyVeryLong = setTimeout(() => {
- shellIsReady.cancel();
- Notifications.info(
- "If terminal shell is not ready please check your shell init files, if applicable.",
- {
- timeout: 4_000,
- },
- );
- }, 10_000);
-
- await shellIsReady.catch(noop);
- clearTimeout(notifyVeryLong);
+ tabId = createTerminalTab().id;
}
+ await when(() => Boolean(getTerminalApi(tabId)));
+
const terminalApi = getTerminalApi(tabId);
+ const shellIsReady = when(() =>terminalApi.isReady);
+ const notifyVeryLong = setTimeout(() => {
+ shellIsReady.cancel();
+ Notifications.info(
+ "If terminal shell is not ready please check your shell init files, if applicable.",
+ {
+ timeout: 4_000,
+ },
+ );
+ }, 10_000);
+
+ await shellIsReady.catch(noop);
+ clearTimeout(notifyVeryLong);
if (terminalApi) {
if (options.enter) {
diff --git a/src/renderer/search-store/create-search-store.injectable.ts b/src/renderer/search-store/create-search-store.injectable.ts
new file mode 100644
index 0000000000..088a837f8c
--- /dev/null
+++ b/src/renderer/search-store/create-search-store.injectable.ts
@@ -0,0 +1,13 @@
+/**
+ * Copyright (c) OpenLens Authors. All rights reserved.
+ * Licensed under MIT License. See LICENSE in root directory for more information.
+ */
+import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
+import { SearchStore } from "./search-store";
+
+const createSearchStoreInjectable = getInjectable({
+ instantiate: () => () => new SearchStore(),
+ lifecycle: lifecycleEnum.singleton,
+});
+
+export default createSearchStoreInjectable;