From 5c7314da0a6b95860ebc86b92d05ecb359696478 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 12 Apr 2022 10:23:26 -0400 Subject: [PATCH] fix deployments/scale/dialog.test.tsx Signed-off-by: Sebastian Malton --- .../deployment-menu.tsx | 112 ++++++++++-------- .../scale/dialog-state.injectable.ts | 14 +++ .../dialog.scss} | 0 .../dialog.test.tsx} | 32 +++-- .../dialog.tsx} | 59 ++++----- .../scale/open.injectable.ts | 20 ++++ .../frames/cluster-frame/cluster-frame.tsx | 2 +- 7 files changed, 154 insertions(+), 85 deletions(-) create mode 100644 src/renderer/components/+workloads-deployments/scale/dialog-state.injectable.ts rename src/renderer/components/+workloads-deployments/{deployment-scale-dialog.scss => scale/dialog.scss} (100%) rename src/renderer/components/+workloads-deployments/{deployment-scale-dialog.test.tsx => scale/dialog.test.tsx} (77%) rename src/renderer/components/+workloads-deployments/{deployment-scale-dialog.tsx => scale/dialog.tsx} (75%) create mode 100644 src/renderer/components/+workloads-deployments/scale/open.injectable.ts diff --git a/src/renderer/components/+workloads-deployments/deployment-menu.tsx b/src/renderer/components/+workloads-deployments/deployment-menu.tsx index 38585c0830..696cc0e20b 100644 --- a/src/renderer/components/+workloads-deployments/deployment-menu.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-menu.tsx @@ -4,57 +4,75 @@ */ import React from "react"; import type { KubeObjectMenuProps } from "../kube-object-menu"; -import type { Deployment } from "../../../common/k8s-api/endpoints"; -import { deploymentApi } from "../../../common/k8s-api/endpoints"; +import type { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints"; import { MenuItem } from "../menu"; -import { DeploymentScaleDialog } from "./deployment-scale-dialog"; import { Icon } from "../icon"; import { ConfirmDialog } from "../confirm-dialog"; import { Notifications } from "../notifications"; +import type { OpenDeploymentScaleDialog } from "./scale/open.injectable"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import deploymentApiInjectable from "../../../common/k8s-api/endpoints/deployment.api.injectable"; +import openDeploymentScaleDialogInjectable from "./scale/open.injectable"; -export function DeploymentMenu(props: KubeObjectMenuProps) { - const { object, toolbar } = props; +export interface DeploymentMenuProps extends KubeObjectMenuProps {} - return ( - <> - DeploymentScaleDialog.open(object)}> - - Scale - - ConfirmDialog.open({ - ok: async () => - { - try { - await deploymentApi.restart({ - namespace: object.getNs(), - name: object.getName(), - }); - } catch (err) { - Notifications.checkedError(err, "Unknown error occured while restarting deployment"); - } - }, - labelOk: `Restart`, - message: ( -

- {"Are you sure you want to restart deployment "} - {object.getName()} - ? -

- ), - })} - > - - Restart -
- - ); +interface Dependencies { + openDeploymentScaleDialog: OpenDeploymentScaleDialog; + deploymentApi: DeploymentApi; } + +const NonInjectedDeploymentMenu = ({ + deploymentApi, + object, + openDeploymentScaleDialog, + toolbar, +}: Dependencies & DeploymentMenuProps) => ( + <> + openDeploymentScaleDialog(object)}> + + Scale + + ConfirmDialog.open({ + ok: async () => + { + try { + await deploymentApi.restart({ + namespace: object.getNs(), + name: object.getName(), + }); + } catch (err) { + Notifications.checkedError(err, "Unknown error occured while restarting deployment"); + } + }, + labelOk: "Restart", + message: ( +

+ {"Are you sure you want to restart deployment "} + {object.getName()} + ? +

+ ), + })} + > + + Restart +
+ +); + +export const DeploymentMenu = withInjectables(NonInjectedDeploymentMenu, { + getProps: (di, props) => ({ + ...props, + deploymentApi: di.inject(deploymentApiInjectable), + openDeploymentScaleDialog: di.inject(openDeploymentScaleDialogInjectable), + }), +}); diff --git a/src/renderer/components/+workloads-deployments/scale/dialog-state.injectable.ts b/src/renderer/components/+workloads-deployments/scale/dialog-state.injectable.ts new file mode 100644 index 0000000000..9da03e509f --- /dev/null +++ b/src/renderer/components/+workloads-deployments/scale/dialog-state.injectable.ts @@ -0,0 +1,14 @@ +/** + * 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 { observable } from "mobx"; +import type { Deployment } from "../../../../common/k8s-api/endpoints"; + +const deploymentScaleDialogStateInjectable = getInjectable({ + id: "deployment-scale-dialog-state", + instantiate: () => observable.box(), +}); + +export default deploymentScaleDialogStateInjectable; diff --git a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.scss b/src/renderer/components/+workloads-deployments/scale/dialog.scss similarity index 100% rename from src/renderer/components/+workloads-deployments/deployment-scale-dialog.scss rename to src/renderer/components/+workloads-deployments/scale/dialog.scss diff --git a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.test.tsx b/src/renderer/components/+workloads-deployments/scale/dialog.test.tsx similarity index 77% rename from src/renderer/components/+workloads-deployments/deployment-scale-dialog.test.tsx rename to src/renderer/components/+workloads-deployments/scale/dialog.test.tsx index b100d3e5f0..0ce3d1e8de 100644 --- a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.test.tsx +++ b/src/renderer/components/+workloads-deployments/scale/dialog.test.tsx @@ -4,11 +4,19 @@ */ import React from "react"; -import { render, waitFor, fireEvent } from "@testing-library/react"; +import { waitFor, fireEvent } from "@testing-library/react"; import "@testing-library/jest-dom/extend-expect"; -import { DeploymentScaleDialog } from "./deployment-scale-dialog"; -import { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints/deployment.api"; +import { DeploymentScaleDialog } from "./dialog"; +import type { DeploymentApi } from "../../../../common/k8s-api/endpoints/deployment.api"; +import { Deployment } from "../../../../common/k8s-api/endpoints/deployment.api"; +import { getDiForUnitTesting } from "../../../getDiForUnitTesting"; +import deploymentApiInjectable from "../../../../common/k8s-api/endpoints/deployment.api.injectable"; +import type { OpenDeploymentScaleDialog } from "./open.injectable"; +import openDeploymentScaleDialogInjectable from "./open.injectable"; +import createStoresAndApisInjectable from "../../../create-stores-apis.injectable"; +import type { DiRender } from "../../test-utils/renderFor"; +import { renderFor } from "../../test-utils/renderFor"; const dummyDeployment = new Deployment({ apiVersion: "v1", @@ -76,9 +84,17 @@ const dummyDeployment = new Deployment({ describe("", () => { let deploymentApi: DeploymentApi; + let openDeploymentScaleDialog: OpenDeploymentScaleDialog; + let render: DiRender; beforeEach(() => { - deploymentApi = new DeploymentApi(); + const di = getDiForUnitTesting({ doGeneralOverrides: true }); + + di.override(createStoresAndApisInjectable, () => true); + + deploymentApi = di.inject(deploymentApiInjectable); + openDeploymentScaleDialog = di.inject(openDeploymentScaleDialogInjectable); + render = renderFor(di); }); it("renders w/o errors", () => { @@ -93,9 +109,9 @@ describe("", () => { const initReplicas = 3; deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas); - const { findByTestId } = render(); + const { findByTestId } = render(); - DeploymentScaleDialog.open(dummyDeployment); + openDeploymentScaleDialog(dummyDeployment); // we need to wait for the DeploymentScaleDialog to show up // because there is an in which renders null at start. await waitFor(async () => { @@ -114,9 +130,9 @@ describe("", () => { const initReplicas = 1; deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas); - const component = render(); + const component = render(); - DeploymentScaleDialog.open(dummyDeployment); + openDeploymentScaleDialog(dummyDeployment); await waitFor(async () => { expect(await component.findByTestId("desired-scale")).toHaveTextContent(`${initReplicas}`); expect(await component.findByTestId("current-scale")).toHaveTextContent(`${initReplicas}`); diff --git a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx b/src/renderer/components/+workloads-deployments/scale/dialog.tsx similarity index 75% rename from src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx rename to src/renderer/components/+workloads-deployments/scale/dialog.tsx index f0273114b4..00c953cf4c 100644 --- a/src/renderer/components/+workloads-deployments/deployment-scale-dialog.tsx +++ b/src/renderer/components/+workloads-deployments/scale/dialog.tsx @@ -3,52 +3,45 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import "./deployment-scale-dialog.scss"; +import "./dialog.scss"; import React, { Component } from "react"; +import type { IObservableValue } from "mobx"; import { computed, observable, makeObservable } from "mobx"; import { observer } from "mobx-react"; -import type { DialogProps } from "../dialog"; -import { Dialog } from "../dialog"; -import { Wizard, WizardStep } from "../wizard"; -import type { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints"; -import { deploymentApi } from "../../../common/k8s-api/endpoints"; -import { Icon } from "../icon"; -import { Slider } from "../slider"; -import { Notifications } from "../notifications"; -import { cssNames } from "../../utils"; +import type { DialogProps } from "../../dialog"; +import { Dialog } from "../../dialog"; +import { Wizard, WizardStep } from "../../wizard"; +import type { Deployment, DeploymentApi } from "../../../../common/k8s-api/endpoints"; +import { Icon } from "../../icon"; +import { Slider } from "../../slider"; +import { Notifications } from "../../notifications"; +import { cssNames } from "../../../utils"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import deploymentApiInjectable from "../../../../common/k8s-api/endpoints/deployment.api.injectable"; +import deploymentScaleDialogStateInjectable from "./dialog-state.injectable"; export interface DeploymentScaleDialogProps extends Partial { - deploymentApi: DeploymentApi; } -const dialogState = observable.box(); +interface Dependencies { + deploymentApi: DeploymentApi; + state: IObservableValue; +} @observer -export class DeploymentScaleDialog extends Component { - static defaultProps = { - deploymentApi, - }; - +class NonInjectedDeploymentScaleDialog extends Component { @observable ready = false; @observable currentReplicas = 0; @observable desiredReplicas = 0; - constructor(props: DeploymentScaleDialogProps) { + constructor(props: DeploymentScaleDialogProps & Dependencies) { super(props); makeObservable(this); } - static open(deployment: Deployment) { - dialogState.set(deployment); - } - - static close() { - dialogState.set(undefined); - } - close = () => { - DeploymentScaleDialog.close(); + this.props.state.set(undefined); }; @computed get scaleMax() { @@ -166,8 +159,8 @@ export class DeploymentScaleDialog extends Component } render() { - const { className, ...dialogProps } = this.props; - const deployment = dialogState.get(); + const { className, state, ...dialogProps } = this.props; + const deployment = state.get(); return ( ); } } + +export const DeploymentScaleDialog = withInjectables(NonInjectedDeploymentScaleDialog, { + getProps: (di, props) => ({ + ...props, + deploymentApi: di.inject(deploymentApiInjectable), + state: di.inject(deploymentScaleDialogStateInjectable), + }), +}); diff --git a/src/renderer/components/+workloads-deployments/scale/open.injectable.ts b/src/renderer/components/+workloads-deployments/scale/open.injectable.ts new file mode 100644 index 0000000000..db21f51b34 --- /dev/null +++ b/src/renderer/components/+workloads-deployments/scale/open.injectable.ts @@ -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 type { Deployment } from "../../../../common/k8s-api/endpoints"; +import deploymentScaleDialogStateInjectable from "./dialog-state.injectable"; + +export type OpenDeploymentScaleDialog = (obj: Deployment) => void; + +const openDeploymentScaleDialogInjectable = getInjectable({ + id: "open-deployment-scale-dialog", + instantiate: (di): OpenDeploymentScaleDialog => { + const state = di.inject(deploymentScaleDialogStateInjectable); + + return obj => state.set(obj); + }, +}); + +export default openDeploymentScaleDialogInjectable; diff --git a/src/renderer/frames/cluster-frame/cluster-frame.tsx b/src/renderer/frames/cluster-frame/cluster-frame.tsx index 6e554a13de..f4b59e1258 100755 --- a/src/renderer/frames/cluster-frame/cluster-frame.tsx +++ b/src/renderer/frames/cluster-frame/cluster-frame.tsx @@ -7,7 +7,7 @@ import type { IComputedValue } from "mobx"; import { observer } from "mobx-react"; import { Redirect } from "react-router"; import { ConfirmDialog } from "../../components/confirm-dialog"; -import { DeploymentScaleDialog } from "../../components/+workloads-deployments/deployment-scale-dialog"; +import { DeploymentScaleDialog } from "../../components/+workloads-deployments/scale/dialog"; import { CronJobTriggerDialog } from "../../components/+workloads-cronjobs/cronjob-trigger-dialog"; import { StatefulSetScaleDialog } from "../../components/+workloads-statefulsets/dialog/dialog"; import { ReplicaSetScaleDialog } from "../../components/+workloads-replicasets/scale-dialog/dialog";