mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
fix deployments/scale/dialog.test.tsx
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
24db61fbef
commit
5c7314da0a
@ -4,57 +4,75 @@
|
|||||||
*/
|
*/
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import type { KubeObjectMenuProps } from "../kube-object-menu";
|
import type { KubeObjectMenuProps } from "../kube-object-menu";
|
||||||
import type { Deployment } from "../../../common/k8s-api/endpoints";
|
import type { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints";
|
||||||
import { deploymentApi } from "../../../common/k8s-api/endpoints";
|
|
||||||
import { MenuItem } from "../menu";
|
import { MenuItem } from "../menu";
|
||||||
import { DeploymentScaleDialog } from "./deployment-scale-dialog";
|
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { ConfirmDialog } from "../confirm-dialog";
|
import { ConfirmDialog } from "../confirm-dialog";
|
||||||
import { Notifications } from "../notifications";
|
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<Deployment>) {
|
export interface DeploymentMenuProps extends KubeObjectMenuProps<Deployment> {}
|
||||||
const { object, toolbar } = props;
|
|
||||||
|
|
||||||
return (
|
interface Dependencies {
|
||||||
<>
|
openDeploymentScaleDialog: OpenDeploymentScaleDialog;
|
||||||
<MenuItem onClick={() => DeploymentScaleDialog.open(object)}>
|
deploymentApi: DeploymentApi;
|
||||||
<Icon
|
|
||||||
material="open_with"
|
|
||||||
tooltip="Scale"
|
|
||||||
interactive={toolbar}
|
|
||||||
/>
|
|
||||||
<span className="title">Scale</span>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => 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: (
|
|
||||||
<p>
|
|
||||||
{"Are you sure you want to restart deployment "}
|
|
||||||
<b>{object.getName()}</b>
|
|
||||||
?
|
|
||||||
</p>
|
|
||||||
),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
material="autorenew"
|
|
||||||
tooltip="Restart"
|
|
||||||
interactive={toolbar}
|
|
||||||
/>
|
|
||||||
<span className="title">Restart</span>
|
|
||||||
</MenuItem>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NonInjectedDeploymentMenu = ({
|
||||||
|
deploymentApi,
|
||||||
|
object,
|
||||||
|
openDeploymentScaleDialog,
|
||||||
|
toolbar,
|
||||||
|
}: Dependencies & DeploymentMenuProps) => (
|
||||||
|
<>
|
||||||
|
<MenuItem onClick={() => openDeploymentScaleDialog(object)}>
|
||||||
|
<Icon
|
||||||
|
material="open_with"
|
||||||
|
tooltip="Scale"
|
||||||
|
interactive={toolbar}
|
||||||
|
/>
|
||||||
|
<span className="title">Scale</span>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => 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: (
|
||||||
|
<p>
|
||||||
|
{"Are you sure you want to restart deployment "}
|
||||||
|
<b>{object.getName()}</b>
|
||||||
|
?
|
||||||
|
</p>
|
||||||
|
),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
material="autorenew"
|
||||||
|
tooltip="Restart"
|
||||||
|
interactive={toolbar}
|
||||||
|
/>
|
||||||
|
<span className="title">Restart</span>
|
||||||
|
</MenuItem>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const DeploymentMenu = withInjectables<Dependencies, DeploymentMenuProps>(NonInjectedDeploymentMenu, {
|
||||||
|
getProps: (di, props) => ({
|
||||||
|
...props,
|
||||||
|
deploymentApi: di.inject(deploymentApiInjectable),
|
||||||
|
openDeploymentScaleDialog: di.inject(openDeploymentScaleDialogInjectable),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@ -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<Deployment | undefined>(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default deploymentScaleDialogStateInjectable;
|
||||||
@ -4,11 +4,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
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 "@testing-library/jest-dom/extend-expect";
|
||||||
|
|
||||||
import { DeploymentScaleDialog } from "./deployment-scale-dialog";
|
import { DeploymentScaleDialog } from "./dialog";
|
||||||
import { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints/deployment.api";
|
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({
|
const dummyDeployment = new Deployment({
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
@ -76,9 +84,17 @@ const dummyDeployment = new Deployment({
|
|||||||
|
|
||||||
describe("<DeploymentScaleDialog />", () => {
|
describe("<DeploymentScaleDialog />", () => {
|
||||||
let deploymentApi: DeploymentApi;
|
let deploymentApi: DeploymentApi;
|
||||||
|
let openDeploymentScaleDialog: OpenDeploymentScaleDialog;
|
||||||
|
let render: DiRender;
|
||||||
|
|
||||||
beforeEach(() => {
|
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", () => {
|
it("renders w/o errors", () => {
|
||||||
@ -93,9 +109,9 @@ describe("<DeploymentScaleDialog />", () => {
|
|||||||
const initReplicas = 3;
|
const initReplicas = 3;
|
||||||
|
|
||||||
deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas);
|
deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas);
|
||||||
const { findByTestId } = render(<DeploymentScaleDialog deploymentApi={deploymentApi} />);
|
const { findByTestId } = render(<DeploymentScaleDialog />);
|
||||||
|
|
||||||
DeploymentScaleDialog.open(dummyDeployment);
|
openDeploymentScaleDialog(dummyDeployment);
|
||||||
// we need to wait for the DeploymentScaleDialog to show up
|
// we need to wait for the DeploymentScaleDialog to show up
|
||||||
// because there is an <Animate /> in <Dialog /> which renders null at start.
|
// because there is an <Animate /> in <Dialog /> which renders null at start.
|
||||||
await waitFor(async () => {
|
await waitFor(async () => {
|
||||||
@ -114,9 +130,9 @@ describe("<DeploymentScaleDialog />", () => {
|
|||||||
const initReplicas = 1;
|
const initReplicas = 1;
|
||||||
|
|
||||||
deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas);
|
deploymentApi.getReplicas = jest.fn().mockImplementationOnce(async () => initReplicas);
|
||||||
const component = render(<DeploymentScaleDialog deploymentApi={deploymentApi} />);
|
const component = render(<DeploymentScaleDialog />);
|
||||||
|
|
||||||
DeploymentScaleDialog.open(dummyDeployment);
|
openDeploymentScaleDialog(dummyDeployment);
|
||||||
await waitFor(async () => {
|
await waitFor(async () => {
|
||||||
expect(await component.findByTestId("desired-scale")).toHaveTextContent(`${initReplicas}`);
|
expect(await component.findByTestId("desired-scale")).toHaveTextContent(`${initReplicas}`);
|
||||||
expect(await component.findByTestId("current-scale")).toHaveTextContent(`${initReplicas}`);
|
expect(await component.findByTestId("current-scale")).toHaveTextContent(`${initReplicas}`);
|
||||||
@ -3,52 +3,45 @@
|
|||||||
* 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 "./deployment-scale-dialog.scss";
|
import "./dialog.scss";
|
||||||
|
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
import type { IObservableValue } from "mobx";
|
||||||
import { computed, observable, makeObservable } from "mobx";
|
import { computed, observable, makeObservable } from "mobx";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import type { DialogProps } from "../dialog";
|
import type { DialogProps } from "../../dialog";
|
||||||
import { Dialog } from "../dialog";
|
import { Dialog } from "../../dialog";
|
||||||
import { Wizard, WizardStep } from "../wizard";
|
import { Wizard, WizardStep } from "../../wizard";
|
||||||
import type { Deployment, DeploymentApi } from "../../../common/k8s-api/endpoints";
|
import type { Deployment, DeploymentApi } from "../../../../common/k8s-api/endpoints";
|
||||||
import { deploymentApi } from "../../../common/k8s-api/endpoints";
|
import { Icon } from "../../icon";
|
||||||
import { Icon } from "../icon";
|
import { Slider } from "../../slider";
|
||||||
import { Slider } from "../slider";
|
import { Notifications } from "../../notifications";
|
||||||
import { Notifications } from "../notifications";
|
import { cssNames } from "../../../utils";
|
||||||
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<DialogProps> {
|
export interface DeploymentScaleDialogProps extends Partial<DialogProps> {
|
||||||
deploymentApi: DeploymentApi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialogState = observable.box<Deployment | undefined>();
|
interface Dependencies {
|
||||||
|
deploymentApi: DeploymentApi;
|
||||||
|
state: IObservableValue<Deployment | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class DeploymentScaleDialog extends Component<DeploymentScaleDialogProps> {
|
class NonInjectedDeploymentScaleDialog extends Component<DeploymentScaleDialogProps & Dependencies> {
|
||||||
static defaultProps = {
|
|
||||||
deploymentApi,
|
|
||||||
};
|
|
||||||
|
|
||||||
@observable ready = false;
|
@observable ready = false;
|
||||||
@observable currentReplicas = 0;
|
@observable currentReplicas = 0;
|
||||||
@observable desiredReplicas = 0;
|
@observable desiredReplicas = 0;
|
||||||
|
|
||||||
constructor(props: DeploymentScaleDialogProps) {
|
constructor(props: DeploymentScaleDialogProps & Dependencies) {
|
||||||
super(props);
|
super(props);
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static open(deployment: Deployment) {
|
|
||||||
dialogState.set(deployment);
|
|
||||||
}
|
|
||||||
|
|
||||||
static close() {
|
|
||||||
dialogState.set(undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
close = () => {
|
close = () => {
|
||||||
DeploymentScaleDialog.close();
|
this.props.state.set(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
@computed get scaleMax() {
|
@computed get scaleMax() {
|
||||||
@ -166,8 +159,8 @@ export class DeploymentScaleDialog extends Component<DeploymentScaleDialogProps>
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, ...dialogProps } = this.props;
|
const { className, state, ...dialogProps } = this.props;
|
||||||
const deployment = dialogState.get();
|
const deployment = state.get();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
@ -183,3 +176,11 @@ export class DeploymentScaleDialog extends Component<DeploymentScaleDialogProps>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DeploymentScaleDialog = withInjectables<Dependencies, DeploymentScaleDialogProps>(NonInjectedDeploymentScaleDialog, {
|
||||||
|
getProps: (di, props) => ({
|
||||||
|
...props,
|
||||||
|
deploymentApi: di.inject(deploymentApiInjectable),
|
||||||
|
state: di.inject(deploymentScaleDialogStateInjectable),
|
||||||
|
}),
|
||||||
|
});
|
||||||
@ -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;
|
||||||
@ -7,7 +7,7 @@ import type { IComputedValue } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Redirect } from "react-router";
|
import { Redirect } from "react-router";
|
||||||
import { ConfirmDialog } from "../../components/confirm-dialog";
|
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 { CronJobTriggerDialog } from "../../components/+workloads-cronjobs/cronjob-trigger-dialog";
|
||||||
import { StatefulSetScaleDialog } from "../../components/+workloads-statefulsets/dialog/dialog";
|
import { StatefulSetScaleDialog } from "../../components/+workloads-statefulsets/dialog/dialog";
|
||||||
import { ReplicaSetScaleDialog } from "../../components/+workloads-replicasets/scale-dialog/dialog";
|
import { ReplicaSetScaleDialog } from "../../components/+workloads-replicasets/scale-dialog/dialog";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user