diff --git a/src/common/k8s-api/endpoints/helm-charts.api.ts b/src/common/k8s-api/endpoints/helm-charts.api.ts index 2690e95afb..f4ba0cf45f 100644 --- a/src/common/k8s-api/endpoints/helm-charts.api.ts +++ b/src/common/k8s-api/endpoints/helm-charts.api.ts @@ -315,6 +315,8 @@ export class HelmChart implements HelmChartData { autoBind(this); } + static create(data: RawHelmChart): HelmChart; + static create(data: RawHelmChart, opts?: HelmChartCreateOpts): HelmChart | undefined; static create(data: RawHelmChart, { onError = "throw" }: HelmChartCreateOpts = {}): HelmChart | undefined { const result = helmChartValidator.validate(data, { abortEarly: false, diff --git a/src/renderer/components/+helm-charts/__snapshots__/helm-chart-details.test.tsx.snap b/src/renderer/components/+helm-charts/__snapshots__/helm-chart-details.test.tsx.snap new file mode 100644 index 0000000000..b558d1bef1 --- /dev/null +++ b/src/renderer/components/+helm-charts/__snapshots__/helm-chart-details.test.tsx.snap @@ -0,0 +1,423 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` before getChartDetails resolves renders 1`] = ` + +
+
+
+
+
+
+
+ Chart: a galaxy far far away/a name + + + content_copy + +
+ +
+ + + close + +
+ +
+
+
+
+
+
+
+ +`; + +exports[` before getChartDetails resolves when getChartDetails resolves with one version renders 1`] = ` + +
+
+
+
+
+
+
+ Chart: a galaxy far far away/a name + + + content_copy + +
+ +
+ + + close + +
+ +
+
+
+
+ +
+
+ + +
+
+ + Version + + +
+ + +
+
+
+ 1 +
+
+ +
+
+
+ + +
+
+
+
+
+
+ + Home + + + + +
+
+ + Maintainers + + +
+
+
+
+
+

+ I am a readme +

+ + +
+
+
+
+
+
+
+ +`; + +exports[` before getChartDetails resolves with getChartDetails rejects renders 1`] = ` + +
+
+
+
+ + + info_outline + + +
+
+ Error: some error +
+
+ + + close + + +
+
+
+
+
+
+
+
+ Chart: a galaxy far far away/a name + + + content_copy + +
+ +
+ + + close + +
+ +
+
+
+
+
+
+
+ +`; diff --git a/src/renderer/components/+helm-charts/get-char-details.injectable.ts b/src/renderer/components/+helm-charts/get-char-details.injectable.ts new file mode 100644 index 0000000000..e2c5ccca62 --- /dev/null +++ b/src/renderer/components/+helm-charts/get-char-details.injectable.ts @@ -0,0 +1,17 @@ +/** + * 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 type { GetChartDetailsOptions, IHelmChartDetails } from "../../../common/k8s-api/endpoints/helm-charts.api"; +import { getChartDetails } from "../../../common/k8s-api/endpoints/helm-charts.api"; + +export type GetChartDetails = (repo: string, name: string, opts?: GetChartDetailsOptions) => Promise; + +const getChartDetailsInjectable = getInjectable({ + id: "get-chart-details", + instantiate: (): GetChartDetails => getChartDetails, + causesSideEffects: true, +}); + +export default getChartDetailsInjectable; diff --git a/src/renderer/components/+helm-charts/helm-chart-details.scss b/src/renderer/components/+helm-charts/helm-chart-details.scss index 9f6d64223d..b82512dff4 100644 --- a/src/renderer/components/+helm-charts/helm-chart-details.scss +++ b/src/renderer/components/+helm-charts/helm-chart-details.scss @@ -14,6 +14,10 @@ box-sizing: content-box; } + div.intro-logo { + width: 100px; + } + .Select__option { span.deprecated { text-decoration: line-through; diff --git a/src/renderer/components/+helm-charts/helm-chart-details.test.tsx b/src/renderer/components/+helm-charts/helm-chart-details.test.tsx new file mode 100644 index 0000000000..4af6543a9d --- /dev/null +++ b/src/renderer/components/+helm-charts/helm-chart-details.test.tsx @@ -0,0 +1,92 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { AsyncFnMock } from "@async-fn/jest"; +import asyncFn from "@async-fn/jest"; +import type { DiContainer } from "@ogre-tools/injectable"; +import type { RenderResult } from "@testing-library/react"; +import React from "react"; +import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; +import { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; +import { getDiForUnitTesting } from "../../getDiForUnitTesting"; +import { noop } from "../../utils"; +import type { CreateInstallChartTab } from "../dock/install-chart/create-install-chart-tab.injectable"; +import createInstallChartTabInjectable from "../dock/install-chart/create-install-chart-tab.injectable"; +import { Notifications } from "../notifications"; +import type { DiRender } from "../test-utils/renderFor"; +import { renderFor } from "../test-utils/renderFor"; +import type { GetChartDetails } from "./get-char-details.injectable"; +import getChartDetailsInjectable from "./get-char-details.injectable"; +import { HelmChartDetails } from "./helm-chart-details"; + +describe("", () => { + let di: DiContainer; + let getChartDetails: AsyncFnMock; + let chart: HelmChart; + let render: DiRender; + let result: RenderResult; + let createInstallChartTab: jest.MockedFunction; + + beforeEach(() => { + di = getDiForUnitTesting({ doGeneralOverrides: true }); + getChartDetails = asyncFn(); + createInstallChartTab = jest.fn(); + chart = HelmChart.create({ + apiVersion: "some-api-version", + created: "a long time ago", + name: "a name", + repo: "a galaxy far far away", + version: "1", + }); + + di.override(directoryForLensLocalStorageInjectable, () => "some-directory-for-lens-local-storage"); + di.override(getChartDetailsInjectable, () => getChartDetails); + di.override(createInstallChartTabInjectable, () => createInstallChartTab); + render = renderFor(di); + result = render(( + <> + + + + )); + }); + + describe("before getChartDetails resolves", () => { + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + describe("when getChartDetails resolves with one version", () => { + beforeEach(async () => { + await getChartDetails.resolve({ + readme: "I am a readme", + versions: [chart], + }); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + it("shows the readme", () => { + expect(result.queryByTestId("helmchart-readme")).not.toBeNull(); + }); + + it("shows the selected chart", () => { + expect(result.queryByTestId("selected-chart-description")).not.toBeNull(); + }); + }); + + describe("with getChartDetails rejects", () => { + beforeEach(async () => { + await getChartDetails.reject(new Error("some error")); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + }); + }); +}); diff --git a/src/renderer/components/+helm-charts/helm-chart-details.tsx b/src/renderer/components/+helm-charts/helm-chart-details.tsx index 4e0076e068..e33f2836ae 100644 --- a/src/renderer/components/+helm-charts/helm-chart-details.tsx +++ b/src/renderer/components/+helm-charts/helm-chart-details.tsx @@ -7,7 +7,6 @@ import "./helm-chart-details.scss"; import React, { Component } from "react"; import type { HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api"; -import { getChartDetails } from "../../../common/k8s-api/endpoints/helm-charts.api"; import { computed, observable, reaction, runInAction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { Drawer, DrawerItem } from "../drawer"; @@ -20,10 +19,13 @@ import { Badge } from "../badge"; import { Tooltip, withStyles } from "@material-ui/core"; import { withInjectables } from "@ogre-tools/injectable-react"; import createInstallChartTabInjectable from "../dock/install-chart/create-install-chart-tab.injectable"; -import { Notifications } from "../notifications"; -import HelmLogoPlaceholder from "./helm-placeholder.svg"; +import type { ShowCheckedErrorNotification } from "../notifications/show-checked-error.injectable"; import type { SingleValue } from "react-select"; -import { AbortController } from "abort-controller"; +import AbortController from "abort-controller"; +import showCheckedErrorNotificationInjectable from "../notifications/show-checked-error.injectable"; +import type { GetChartDetails } from "./get-char-details.injectable"; +import getChartDetailsInjectable from "./get-char-details.injectable"; +import { HelmChartIcon } from "./icon"; export interface HelmChartDetailsProps { chart: HelmChart; @@ -38,6 +40,8 @@ const LargeTooltip = withStyles({ interface Dependencies { createInstallChartTab: (helmChart: HelmChart) => void; + showCheckedErrorNotification: ShowCheckedErrorNotification; + getChartDetails: GetChartDetails; } @observer @@ -73,7 +77,7 @@ class NonInjectedHelmChartDetails extends Component { this.readme.set(readme); @@ -81,7 +85,7 @@ class NonInjectedHelmChartDetails extends Component - event.currentTarget.src = HelmLogoPlaceholder} />
-
+
{selectedChart.getDescription()}