mirror of
https://github.com/prymitive/karma
synced 2026-05-11 03:46:48 +00:00
fix(ui): rewrite SilenceModalContent with hooks
This commit is contained in:
committed by
Łukasz Mierzwa
parent
9dfe40c837
commit
60aa13d3b6
@@ -1,7 +1,7 @@
|
||||
import React, { Component } from "react";
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { observer } from "mobx-react";
|
||||
import { useObserver } from "mobx-react";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faLock } from "@fortawesome/free-solid-svg-icons/faLock";
|
||||
@@ -28,110 +28,94 @@ const ReadOnlyPlaceholder = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const SilenceModalContent = observer(
|
||||
class SilenceModalContent extends Component {
|
||||
static propTypes = {
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
|
||||
settingsStore: PropTypes.instanceOf(Settings).isRequired,
|
||||
onHide: PropTypes.func.isRequired,
|
||||
previewOpen: PropTypes.bool,
|
||||
onDeleteModalClose: PropTypes.func.isRequired,
|
||||
};
|
||||
static defaultProps = {
|
||||
previewOpen: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
settingsStore,
|
||||
onHide,
|
||||
previewOpen,
|
||||
onDeleteModalClose,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="modal-header py-2">
|
||||
<nav className="nav nav-pills nav-justified w-100">
|
||||
<Tab
|
||||
title={
|
||||
silenceFormStore.data.currentStage ===
|
||||
SilenceFormStage.UserInput
|
||||
? silenceFormStore.data.silenceID === null
|
||||
? "New silence"
|
||||
: "Editing silence"
|
||||
: silenceFormStore.data.currentStage ===
|
||||
SilenceFormStage.Preview
|
||||
? "Preview silenced alerts"
|
||||
: "Silence submitted"
|
||||
}
|
||||
active={silenceFormStore.tab.current === SilenceTabNames.Editor}
|
||||
onClick={() =>
|
||||
silenceFormStore.tab.setTab(SilenceTabNames.Editor)
|
||||
}
|
||||
/>
|
||||
<Tab
|
||||
title="Browse"
|
||||
active={
|
||||
silenceFormStore.tab.current === SilenceTabNames.Browser
|
||||
}
|
||||
onClick={() =>
|
||||
silenceFormStore.tab.setTab(SilenceTabNames.Browser)
|
||||
}
|
||||
/>
|
||||
<button type="button" className="close" onClick={onHide}>
|
||||
<span>×</span>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
<div
|
||||
className={`modal-body ${
|
||||
silenceFormStore.toggle.blurred ? "modal-content-blur" : ""
|
||||
}`}
|
||||
>
|
||||
{silenceFormStore.tab.current === SilenceTabNames.Editor ? (
|
||||
silenceFormStore.data.currentStage ===
|
||||
SilenceFormStage.UserInput ? (
|
||||
Object.keys(alertStore.data.clustersWithoutReadOnly).length >
|
||||
0 ? (
|
||||
<SilenceForm
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
settingsStore={settingsStore}
|
||||
previewOpen={previewOpen}
|
||||
/>
|
||||
) : (
|
||||
<ReadOnlyPlaceholder />
|
||||
)
|
||||
) : silenceFormStore.data.currentStage ===
|
||||
SilenceFormStage.Preview ? (
|
||||
<SilencePreview
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
) : (
|
||||
<SilenceSubmitController
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
)
|
||||
) : null}
|
||||
{silenceFormStore.tab.current === SilenceTabNames.Browser ? (
|
||||
<Browser
|
||||
const SilenceModalContent = ({
|
||||
alertStore,
|
||||
silenceFormStore,
|
||||
settingsStore,
|
||||
onHide,
|
||||
previewOpen,
|
||||
onDeleteModalClose,
|
||||
}) => {
|
||||
return useObserver(() => (
|
||||
<React.Fragment>
|
||||
<div className="modal-header py-2">
|
||||
<nav className="nav nav-pills nav-justified w-100">
|
||||
<Tab
|
||||
title={
|
||||
silenceFormStore.data.currentStage === SilenceFormStage.UserInput
|
||||
? silenceFormStore.data.silenceID === null
|
||||
? "New silence"
|
||||
: "Editing silence"
|
||||
: silenceFormStore.data.currentStage ===
|
||||
SilenceFormStage.Preview
|
||||
? "Preview silenced alerts"
|
||||
: "Silence submitted"
|
||||
}
|
||||
active={silenceFormStore.tab.current === SilenceTabNames.Editor}
|
||||
onClick={() => silenceFormStore.tab.setTab(SilenceTabNames.Editor)}
|
||||
/>
|
||||
<Tab
|
||||
title="Browse"
|
||||
active={silenceFormStore.tab.current === SilenceTabNames.Browser}
|
||||
onClick={() => silenceFormStore.tab.setTab(SilenceTabNames.Browser)}
|
||||
/>
|
||||
<button type="button" className="close" onClick={onHide}>
|
||||
<span>×</span>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
<div
|
||||
className={`modal-body ${
|
||||
silenceFormStore.toggle.blurred ? "modal-content-blur" : ""
|
||||
}`}
|
||||
>
|
||||
{silenceFormStore.tab.current === SilenceTabNames.Editor ? (
|
||||
silenceFormStore.data.currentStage === SilenceFormStage.UserInput ? (
|
||||
Object.keys(alertStore.data.clustersWithoutReadOnly).length > 0 ? (
|
||||
<SilenceForm
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
settingsStore={settingsStore}
|
||||
onDeleteModalClose={onDeleteModalClose}
|
||||
previewOpen={previewOpen}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
) : (
|
||||
<ReadOnlyPlaceholder />
|
||||
)
|
||||
) : silenceFormStore.data.currentStage ===
|
||||
SilenceFormStage.Preview ? (
|
||||
<SilencePreview
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
) : (
|
||||
<SilenceSubmitController
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
/>
|
||||
)
|
||||
) : null}
|
||||
{silenceFormStore.tab.current === SilenceTabNames.Browser ? (
|
||||
<Browser
|
||||
alertStore={alertStore}
|
||||
silenceFormStore={silenceFormStore}
|
||||
settingsStore={settingsStore}
|
||||
onDeleteModalClose={onDeleteModalClose}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
));
|
||||
};
|
||||
SilenceModalContent.propTypes = {
|
||||
alertStore: PropTypes.instanceOf(AlertStore).isRequired,
|
||||
silenceFormStore: PropTypes.instanceOf(SilenceFormStore).isRequired,
|
||||
settingsStore: PropTypes.instanceOf(Settings).isRequired,
|
||||
onHide: PropTypes.func.isRequired,
|
||||
previewOpen: PropTypes.bool,
|
||||
onDeleteModalClose: PropTypes.func.isRequired,
|
||||
};
|
||||
SilenceModalContent.defaultProps = {
|
||||
previewOpen: false,
|
||||
};
|
||||
|
||||
export { SilenceModalContent };
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from "react";
|
||||
|
||||
import { shallow } from "enzyme";
|
||||
import { mount } from "enzyme";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
import {
|
||||
@@ -16,6 +17,8 @@ let settingsStore;
|
||||
let silenceFormStore;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(React, "useContext").mockImplementation(() => MockThemeContext);
|
||||
|
||||
alertStore = new AlertStore([]);
|
||||
settingsStore = new Settings();
|
||||
silenceFormStore = new SilenceFormStore();
|
||||
@@ -44,8 +47,8 @@ afterEach(() => {
|
||||
|
||||
const MockOnHide = jest.fn();
|
||||
|
||||
const ShallowSilenceModalContent = () => {
|
||||
return shallow(
|
||||
const MountedSilenceModalContent = () => {
|
||||
return mount(
|
||||
<SilenceModalContent
|
||||
alertStore={alertStore}
|
||||
settingsStore={settingsStore}
|
||||
@@ -59,22 +62,23 @@ const ShallowSilenceModalContent = () => {
|
||||
describe("<SilenceModalContent />", () => {
|
||||
it("Renders ReadOnlyPlaceholder when there are no writable Alertmanager upstreams", () => {
|
||||
alertStore.data.upstreams.instances[0].readonly = true;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const placeholder = tree.find("ReadOnlyPlaceholder");
|
||||
expect(placeholder).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("Clicking on the Browser tab changes content", () => {
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const tabs = tree.find("Tab");
|
||||
tabs.at(1).simulate("click");
|
||||
tree.update();
|
||||
const form = tree.find("Browser");
|
||||
expect(form).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("Clicking on the Editor tab changes content", () => {
|
||||
silenceFormStore.tab.current = SilenceTabNames.Browser;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const tabs = tree.find("Tab");
|
||||
tabs.at(0).simulate("click");
|
||||
const form = tree.find("SilenceForm");
|
||||
@@ -83,13 +87,13 @@ describe("<SilenceModalContent />", () => {
|
||||
|
||||
it("Content is not blurred when silenceFormStore.toggle.blurred is false", () => {
|
||||
silenceFormStore.toggle.blurred = false;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
expect(tree.find("div.modal-body.modal-content-blur")).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("Content is blurred when silenceFormStore.toggle.blurred is true", () => {
|
||||
silenceFormStore.toggle.blurred = true;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
expect(tree.find("div.modal-body.modal-content-blur")).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
@@ -98,49 +102,49 @@ describe("<SilenceModalContent /> Editor", () => {
|
||||
it("title is 'New silence' when creating new silence", () => {
|
||||
silenceFormStore.data.currentStage = SilenceFormStage.UserInput;
|
||||
silenceFormStore.data.silenceID = null;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const tab = tree.find("Tab").at(0);
|
||||
expect(tab.props().title).toBe("New silence");
|
||||
});
|
||||
it("title is 'Editing silence' when editing exiting silence", () => {
|
||||
silenceFormStore.data.currentStage = SilenceFormStage.UserInput;
|
||||
silenceFormStore.data.silenceID = "1234";
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const tab = tree.find("Tab").at(0);
|
||||
expect(tab.props().title).toBe("Editing silence");
|
||||
});
|
||||
it("title is 'Preview silenced alerts' when previewing silenced alerts", () => {
|
||||
silenceFormStore.data.currentStage = SilenceFormStage.Preview;
|
||||
silenceFormStore.data.silenceID = "1234";
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const tab = tree.find("Tab").at(0);
|
||||
expect(tab.props().title).toBe("Preview silenced alerts");
|
||||
});
|
||||
it("title is 'Silence submitted' after sending silence to Alertmanager", () => {
|
||||
silenceFormStore.data.currentStage = SilenceFormStage.Submit;
|
||||
silenceFormStore.data.silenceID = "1234";
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const tab = tree.find("Tab").at(0);
|
||||
expect(tab.props().title).toBe("Silence submitted");
|
||||
});
|
||||
|
||||
it("renders SilenceForm when silenceFormStore.data.currentStage is 'UserInput'", () => {
|
||||
silenceFormStore.data.currentStage = SilenceFormStage.UserInput;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const form = tree.find("SilenceForm");
|
||||
expect(form).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("renders SilencePreview when silenceFormStore.data.currentStage is 'Preview'", () => {
|
||||
silenceFormStore.data.currentStage = SilenceFormStage.Preview;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const ctrl = tree.find("SilencePreview");
|
||||
expect(ctrl).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("renders SilenceSubmitController when silenceFormStore.data.currentStage is 'Submit'", () => {
|
||||
silenceFormStore.data.currentStage = SilenceFormStage.Submit;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const ctrl = tree.find("SilenceSubmitController");
|
||||
expect(ctrl).toHaveLength(1);
|
||||
});
|
||||
@@ -149,7 +153,7 @@ describe("<SilenceModalContent /> Editor", () => {
|
||||
describe("<SilenceModalContent /> Browser", () => {
|
||||
it("renders silence browser when tab is set to Browser", () => {
|
||||
silenceFormStore.tab.current = SilenceTabNames.Browser;
|
||||
const tree = ShallowSilenceModalContent();
|
||||
const tree = MountedSilenceModalContent();
|
||||
const form = tree.find("Browser");
|
||||
expect(form).toHaveLength(1);
|
||||
});
|
||||
|
||||
@@ -162,7 +162,7 @@ describe("<SilenceModal />", () => {
|
||||
silenceFormStore.toggle.visible = true;
|
||||
MountedSilenceModal();
|
||||
|
||||
expect(callbacks).toHaveLength(4);
|
||||
expect(callbacks.length).toBeGreaterThan(0);
|
||||
act(() => {
|
||||
callbacks.forEach((f) => f());
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user