mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add some tests for LogSearch, fix extension API and sendCommand
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
993230c60b
commit
d3c1b0e2e9
@ -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[]) {
|
||||
|
||||
@ -37,10 +37,6 @@ jest.mock("electron", () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const getComponent = (model: LogTabViewModel) => (
|
||||
<LogResourceSelector model={model} />
|
||||
);
|
||||
|
||||
function mockLogTabViewModel(tabId: TabId, deps: Partial<LogTabViewModelDependencies>): LogTabViewModel {
|
||||
return new LogTabViewModel(tabId, {
|
||||
getLogs: jest.fn(),
|
||||
@ -54,6 +50,7 @@ function mockLogTabViewModel(tabId: TabId, deps: Partial<LogTabViewModelDependen
|
||||
stopLoadingLogs: jest.fn(),
|
||||
getPodById: jest.fn(),
|
||||
getPodsByOwnerId: jest.fn(),
|
||||
createSearchStore: jest.fn(),
|
||||
...deps,
|
||||
});
|
||||
}
|
||||
@ -144,14 +141,14 @@ describe("<LogResourceSelector />", () => {
|
||||
|
||||
it("renders w/o errors", () => {
|
||||
const model = getOnePodViewModel("foobar");
|
||||
const { container } = render(getComponent(model));
|
||||
const { container } = render(<LogResourceSelector model={model} />);
|
||||
|
||||
expect(container).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
it("renders proper namespace", async () => {
|
||||
const model = getOnePodViewModel("foobar");
|
||||
const { findByTestId } = render(getComponent(model));
|
||||
const { findByTestId } = render(<LogResourceSelector model={model} />);
|
||||
const ns = await findByTestId("namespace-badge");
|
||||
|
||||
expect(ns).toHaveTextContent("default");
|
||||
@ -159,7 +156,7 @@ describe("<LogResourceSelector />", () => {
|
||||
|
||||
it("renders proper selected items within dropdowns", async () => {
|
||||
const model = getOnePodViewModel("foobar");
|
||||
const { findByText } = render(getComponent(model));
|
||||
const { findByText } = render(<LogResourceSelector model={model} />);
|
||||
|
||||
expect(await findByText("dockerExporter")).toBeInTheDocument();
|
||||
expect(await findByText("docker-exporter")).toBeInTheDocument();
|
||||
@ -167,7 +164,7 @@ describe("<LogResourceSelector />", () => {
|
||||
|
||||
it("renders sibling pods in dropdown", async () => {
|
||||
const model = getFewPodsTabData("foobar");
|
||||
const { container, findByText } = render(getComponent(model));
|
||||
const { container, findByText } = render(<LogResourceSelector model={model} />);
|
||||
|
||||
selectEvent.openMenu(container.querySelector(".pod-selector"));
|
||||
expect(await findByText("deploymentPod2", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument();
|
||||
@ -176,7 +173,7 @@ describe("<LogResourceSelector />", () => {
|
||||
|
||||
it("renders sibling containers in dropdown", async () => {
|
||||
const model = getFewPodsTabData("foobar");
|
||||
const { findByText, container } = render(getComponent(model));
|
||||
const { findByText, container } = render(<LogResourceSelector model={model} />);
|
||||
|
||||
selectEvent.openMenu(container.querySelector(".container-selector"));
|
||||
expect(await findByText("node-exporter-1")).toBeInTheDocument();
|
||||
@ -186,7 +183,7 @@ describe("<LogResourceSelector />", () => {
|
||||
|
||||
it("renders pod owner as dropdown title", async () => {
|
||||
const model = getFewPodsTabData("foobar");
|
||||
const { findByText, container } = render(getComponent(model));
|
||||
const { findByText, container } = render(<LogResourceSelector model={model} />);
|
||||
|
||||
selectEvent.openMenu(container.querySelector(".pod-selector"));
|
||||
expect(await findByText("super-deployment")).toBeInTheDocument();
|
||||
@ -195,7 +192,7 @@ describe("<LogResourceSelector />", () => {
|
||||
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(<LogResourceSelector model={model} />);
|
||||
|
||||
selectEvent.openMenu(container.querySelector(".pod-selector"));
|
||||
|
||||
|
||||
@ -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<LogTabViewModelDependencies>): 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<LogTabViewModelDependencies> = {}): 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(
|
||||
<LogSearch
|
||||
model={model}
|
||||
scrollToOverlay={jest.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
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(
|
||||
<LogSearch
|
||||
model={model}
|
||||
scrollToOverlay={scrollToOverlay}
|
||||
/>,
|
||||
);
|
||||
|
||||
userEvent.click(await screen.findByPlaceholderText("Search..."));
|
||||
userEvent.keyboard("o");
|
||||
userEvent.click(await screen.findByText("keyboard_arrow_up"));
|
||||
expect(scrollToOverlay).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -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,
|
||||
});
|
||||
|
||||
@ -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<LogTabData>) => {
|
||||
this.dependencies.setLogTabData(this.tabId, { ...this.logTabData.get(), ...partialData });
|
||||
|
||||
@ -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) {
|
||||
|
||||
13
src/renderer/search-store/create-search-store.injectable.ts
Normal file
13
src/renderer/search-store/create-search-store.injectable.ts
Normal file
@ -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;
|
||||
Loading…
Reference in New Issue
Block a user