mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
feat(ui): drop moment.js to reduce bundle size
This commit is contained in:
committed by
Łukasz Mierzwa
parent
fdf8824a60
commit
6a7cc1c72f
Generated
+5
-10
@@ -8769,6 +8769,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.14.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.14.0.tgz",
|
||||
"integrity": "sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
@@ -15834,11 +15839,6 @@
|
||||
"traverse": "^0.6.6"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.26.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
|
||||
"integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
|
||||
},
|
||||
"moo": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz",
|
||||
@@ -19251,11 +19251,6 @@
|
||||
"prop-types": "^15.5.10"
|
||||
}
|
||||
},
|
||||
"react-moment": {
|
||||
"version": "0.9.7",
|
||||
"resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz",
|
||||
"integrity": "sha512-ifzUrUGF6KRsUN2pRG5k56kO0mJBr8kRkWb0wNvtFIsBIxOuPxhUpL1YlXwpbQCbHq23hUu6A0VEk64HsFxk9g=="
|
||||
},
|
||||
"react-popper": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.3.tgz",
|
||||
|
||||
+1
-2
@@ -21,6 +21,7 @@
|
||||
"bricks.js": "1.8.0",
|
||||
"copy-to-clipboard": "3.3.1",
|
||||
"csshake": "1.5.3",
|
||||
"date-fns": "2.14.0",
|
||||
"favico.js": "0.3.10",
|
||||
"fontfaceobserver": "2.1.0",
|
||||
"lodash.debounce": "4.0.8",
|
||||
@@ -30,7 +31,6 @@
|
||||
"mobx": "5.15.4",
|
||||
"mobx-react-lite": "2.0.7",
|
||||
"mobx-stored": "1.1.0",
|
||||
"moment": "2.26.0",
|
||||
"promise-retry": "2.0.1",
|
||||
"prop-types": "15.7.2",
|
||||
"qs": "6.9.4",
|
||||
@@ -47,7 +47,6 @@
|
||||
"react-json-pretty": "2.2.0",
|
||||
"react-linkify": "0.2.2",
|
||||
"react-media": "1.10.0",
|
||||
"react-moment": "0.9.7",
|
||||
"react-popper": "2.2.3",
|
||||
"react-resize-detector": "5.0.6",
|
||||
"react-reveal": "1.2.2",
|
||||
|
||||
@@ -45,12 +45,6 @@ const FaviconBadge = React.lazy(() =>
|
||||
}))
|
||||
);
|
||||
|
||||
const MomentPolledTimer = React.lazy(() =>
|
||||
import("Components/MomentPolledTimer").then((module) => ({
|
||||
default: module.MomentPolledTimer,
|
||||
}))
|
||||
);
|
||||
|
||||
interface UIDefaults {
|
||||
Refresh: number;
|
||||
HideFiltersWhenIdle: boolean;
|
||||
@@ -162,7 +156,6 @@ const App: FunctionComponent<AppProps> = ({ defaultFilters, uiDefaults }) => {
|
||||
<React.Suspense fallback={null}>
|
||||
<FaviconBadge alertStore={alertStore} />
|
||||
<Fetcher alertStore={alertStore} settingsStore={settingsStore} />
|
||||
<MomentPolledTimer />
|
||||
</React.Suspense>
|
||||
</ErrorBoundary>
|
||||
));
|
||||
|
||||
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
|
||||
import { toJS } from "mobx";
|
||||
import { useObserver } from "mobx-react-lite";
|
||||
|
||||
import moment from "moment";
|
||||
import addSeconds from "date-fns/addSeconds";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCheck } from "@fortawesome/free-solid-svg-icons/faCheck";
|
||||
@@ -62,17 +62,16 @@ const AlertAck = ({ alertStore, silenceFormStore, group }) => {
|
||||
const commentPrefix = toJS(
|
||||
alertStore.settings.values.alertAcknowledgement.commentPrefix
|
||||
);
|
||||
const now = new Date();
|
||||
c.push({
|
||||
payload: GenerateAlertmanagerSilenceData(
|
||||
moment.utc(),
|
||||
moment.utc().add(durationSeconds, "seconds"),
|
||||
now,
|
||||
addSeconds(now, durationSeconds),
|
||||
MatchersFromGroup(group, [], group.alerts, true),
|
||||
author,
|
||||
`${
|
||||
commentPrefix ? commentPrefix + " " : ""
|
||||
}This alert was acknowledged using karma on ${moment
|
||||
.utc()
|
||||
.toString()}`
|
||||
}This alert was acknowledged using karma on ${now.toUTCString()}`
|
||||
),
|
||||
clusterName: clusterName,
|
||||
members: clusterMembers,
|
||||
|
||||
@@ -250,7 +250,7 @@ describe("<AlertAck />", () => {
|
||||
await MountAndClick();
|
||||
expect(JSON.parse(fetchMock.calls()[0][1].body)).toEqual({
|
||||
comment:
|
||||
"PREFIX This alert was acknowledged using karma on Tue Feb 01 2000 00:00:00 GMT+0000",
|
||||
"PREFIX This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
createdBy: "karma/ui",
|
||||
endsAt: "2000-02-01T00:02:03.000Z",
|
||||
matchers: [
|
||||
@@ -268,7 +268,7 @@ describe("<AlertAck />", () => {
|
||||
await MountAndClick();
|
||||
expect(JSON.parse(fetchMock.calls()[0][1].body)).toEqual({
|
||||
comment:
|
||||
"This alert was acknowledged using karma on Tue Feb 01 2000 00:00:00 GMT+0000",
|
||||
"This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
createdBy: "me",
|
||||
endsAt: "2000-02-01T00:03:57.000Z",
|
||||
matchers: [
|
||||
@@ -288,7 +288,7 @@ describe("<AlertAck />", () => {
|
||||
await MountAndClick();
|
||||
expect(JSON.parse(fetchMock.calls()[0][1].body)).toEqual({
|
||||
comment:
|
||||
"FOO: This alert was acknowledged using karma on Tue Feb 01 2000 00:00:00 GMT+0000",
|
||||
"FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
createdBy: "auth@example.com",
|
||||
endsAt: "2000-02-01T00:03:42.000Z",
|
||||
matchers: [
|
||||
@@ -309,7 +309,7 @@ describe("<AlertAck />", () => {
|
||||
await MountAndClick();
|
||||
expect(JSON.parse(fetchMock.calls()[0][1].body)).toEqual({
|
||||
comment:
|
||||
"FOO: This alert was acknowledged using karma on Tue Feb 01 2000 00:00:00 GMT+0000",
|
||||
"FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
createdBy: "bob@example.com",
|
||||
endsAt: "2000-02-01T00:03:42.000Z",
|
||||
matchers: [
|
||||
@@ -328,7 +328,7 @@ describe("<AlertAck />", () => {
|
||||
await MountAndClick();
|
||||
expect(JSON.parse(fetchMock.calls()[0][1].body)).toEqual({
|
||||
comment:
|
||||
"FOO: This alert was acknowledged using karma on Tue Feb 01 2000 00:00:00 GMT+0000",
|
||||
"FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
createdBy: "me",
|
||||
endsAt: "2000-02-01T00:03:42.000Z",
|
||||
matchers: [
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from "react";
|
||||
|
||||
import { mount } from "enzyme";
|
||||
|
||||
import addSeconds from "date-fns/addSeconds";
|
||||
import subSeconds from "date-fns/subSeconds";
|
||||
|
||||
import { DateFromNow } from ".";
|
||||
|
||||
describe("<DateFromNow />", () => {
|
||||
it("renders 'just now' for now", () => {
|
||||
const tree = mount(<DateFromNow timestamp={new Date().toISOString()} />);
|
||||
expect(tree.text()).toBe("just now");
|
||||
});
|
||||
|
||||
it("renders 'a few seconds ago' for 35 seconds old timestamp", () => {
|
||||
const tree = mount(
|
||||
<DateFromNow timestamp={subSeconds(new Date(), 35).toISOString()} />
|
||||
);
|
||||
expect(tree.text()).toBe("a few seconds ago");
|
||||
});
|
||||
|
||||
it("renders 'in a few seconds' for a timestamp 35 seconds away", () => {
|
||||
const tree = mount(
|
||||
<DateFromNow timestamp={addSeconds(new Date(), 35).toISOString()} />
|
||||
);
|
||||
expect(tree.text()).toBe("in a few seconds");
|
||||
});
|
||||
|
||||
it("renders '1 minute ago' for 65 seconds old timestamp", () => {
|
||||
const tree = mount(
|
||||
<DateFromNow timestamp={subSeconds(new Date(), 65).toISOString()} />
|
||||
);
|
||||
expect(tree.text()).toBe("1 minute ago");
|
||||
});
|
||||
|
||||
it("renders 'in 1 minute' for a timestamp 65 seconds away", () => {
|
||||
const tree = mount(
|
||||
<DateFromNow timestamp={addSeconds(new Date(), 65).toISOString()} />
|
||||
);
|
||||
expect(tree.text()).toBe("in 1 minute");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import React, { FunctionComponent, useState, useEffect } from "react";
|
||||
|
||||
import parseISO from "date-fns/parseISO";
|
||||
import differenceInSeconds from "date-fns/differenceInSeconds";
|
||||
import formatDistanceToNowStrict from "date-fns/formatDistanceToNowStrict";
|
||||
|
||||
const formatLabel = (timestamp: string) => {
|
||||
const ts = parseISO(timestamp);
|
||||
const diff = differenceInSeconds(new Date(), ts);
|
||||
if (diff > 0 && diff < 60) return "a few seconds ago";
|
||||
if (diff < 0 && diff >= -60) return "in a few seconds";
|
||||
if (diff === 0) return "just now";
|
||||
return formatDistanceToNowStrict(ts, {
|
||||
addSuffix: true,
|
||||
});
|
||||
};
|
||||
|
||||
export const DateFromNow: FunctionComponent<{ timestamp: string }> = ({
|
||||
timestamp,
|
||||
}) => {
|
||||
const [label, setLabel] = useState(formatLabel(timestamp));
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(
|
||||
() => setLabel(formatLabel(timestamp)),
|
||||
30 * 1000
|
||||
);
|
||||
return () => clearInterval(timer);
|
||||
}, [timestamp]);
|
||||
|
||||
return <React.Fragment>{label}</React.Fragment>;
|
||||
};
|
||||
@@ -3,7 +3,7 @@ import PropTypes from "prop-types";
|
||||
|
||||
import { reaction } from "mobx";
|
||||
|
||||
import moment from "moment";
|
||||
import addSeconds from "date-fns/addSeconds";
|
||||
|
||||
import { AlertStore, AlertStoreStatuses } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
@@ -50,12 +50,12 @@ const Fetcher = ({ alertStore, settingsStore }) => {
|
||||
};
|
||||
|
||||
const fetchIfIdle = () => {
|
||||
const nextTick = moment(alertStore.status.lastUpdateAt).add(
|
||||
settingsStore.fetchConfig.config.interval,
|
||||
"seconds"
|
||||
const nextTick = addSeconds(
|
||||
alertStore.status.lastUpdateAt,
|
||||
settingsStore.fetchConfig.config.interval
|
||||
);
|
||||
|
||||
const pastDeadline = moment().isSameOrAfter(nextTick);
|
||||
const pastDeadline = new Date() >= nextTick;
|
||||
|
||||
const status = alertStore.status.value.toString();
|
||||
const updateInProgress =
|
||||
|
||||
@@ -5,8 +5,6 @@ import { useObserver } from "mobx-react-lite";
|
||||
|
||||
import { Manager, Reference, Popper } from "react-popper";
|
||||
|
||||
import Moment from "react-moment";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCaretDown } from "@fortawesome/free-solid-svg-icons/faCaretDown";
|
||||
import { faBellSlash } from "@fortawesome/free-solid-svg-icons/faBellSlash";
|
||||
@@ -17,6 +15,7 @@ import { AlertStore } from "Stores/AlertStore";
|
||||
import { SilenceFormStore, SilenceTabNames } from "Stores/SilenceFormStore";
|
||||
import { FetchPauser } from "Components/FetchPauser";
|
||||
import { DropdownSlide } from "Components/Animations/DropdownSlide";
|
||||
import { DateFromNow } from "Components/DateFromNow";
|
||||
import { useOnClickOutside } from "Hooks/useOnClickOutside";
|
||||
|
||||
const onSilenceClick = (alertStore, silenceFormStore, group, alert) => {
|
||||
@@ -130,7 +129,7 @@ const AlertMenu = ({
|
||||
style={{ width: "0.8rem" }}
|
||||
icon={faCaretDown}
|
||||
/>
|
||||
<Moment fromNow>{alert.startsAt}</Moment>
|
||||
<DateFromNow timestamp={alert.startsAt} />
|
||||
</span>
|
||||
)}
|
||||
</Reference>
|
||||
|
||||
@@ -75,9 +75,7 @@ exports[`<Alert /> matches snapshot when inhibited 1`] = `
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
<time datetime=\\"1534268200017\\">
|
||||
a day ago
|
||||
</time>
|
||||
1 day ago
|
||||
</span>
|
||||
</span>
|
||||
<div style=\\"display: inline-block; max-width: 100%;\\"
|
||||
@@ -224,9 +222,7 @@ exports[`<Alert /> matches snapshot with showAlertmanagers=false showReceiver=fa
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
<time datetime=\\"1534268200017\\">
|
||||
a day ago
|
||||
</time>
|
||||
1 day ago
|
||||
</span>
|
||||
</span>
|
||||
<div style=\\"display: inline-block; max-width: 100%;\\"
|
||||
|
||||
@@ -7,8 +7,6 @@ import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import Moment from "react-moment";
|
||||
|
||||
import {
|
||||
MockAlert,
|
||||
MockAnnotation,
|
||||
@@ -291,25 +289,62 @@ describe("<Alert />", () => {
|
||||
|
||||
it("alert timestamp is updated every minute", () => {
|
||||
jest.useFakeTimers();
|
||||
Moment.startPooledTimer();
|
||||
|
||||
advanceTo(new Date(Date.UTC(2018, 7, 14, 17, 36, 41)));
|
||||
|
||||
const alert = MockedAlert();
|
||||
const group = MockAlertGroup({}, [alert], [], {}, {});
|
||||
const tree = MountedAlert(alert, group, false, false);
|
||||
expect(tree.find("time").text()).toBe("a few seconds ago");
|
||||
expect(
|
||||
tree
|
||||
.find("span.components-label.badge.badge-secondary.cursor-pointer")
|
||||
.at(0)
|
||||
.text()
|
||||
).toBe("just now");
|
||||
|
||||
advanceTo(new Date(Date.UTC(2018, 7, 14, 17, 36, 42)));
|
||||
act(() => jest.advanceTimersByTime(31 * 1000));
|
||||
expect(
|
||||
tree
|
||||
.find("span.components-label.badge.badge-secondary.cursor-pointer")
|
||||
.at(0)
|
||||
.text()
|
||||
).toBe("a few seconds ago");
|
||||
|
||||
advanceTo(new Date(Date.UTC(2018, 7, 14, 17, 37, 41)));
|
||||
act(() => jest.advanceTimersByTime(61 * 1000));
|
||||
expect(tree.find("time").text()).toBe("a minute ago");
|
||||
act(() => jest.advanceTimersByTime(31 * 1000));
|
||||
expect(
|
||||
tree
|
||||
.find("span.components-label.badge.badge-secondary.cursor-pointer")
|
||||
.at(0)
|
||||
.text()
|
||||
).toBe("1 minute ago");
|
||||
|
||||
advanceTo(new Date(Date.UTC(2018, 7, 14, 18, 36, 41)));
|
||||
jest.advanceTimersByTime(61 * 1000);
|
||||
expect(tree.find("time").text()).toBe("an hour ago");
|
||||
act(() => jest.advanceTimersByTime(31 * 1000));
|
||||
expect(
|
||||
tree
|
||||
.find("span.components-label.badge.badge-secondary.cursor-pointer")
|
||||
.at(0)
|
||||
.text()
|
||||
).toBe("1 hour ago");
|
||||
|
||||
advanceTo(new Date(Date.UTC(2018, 7, 14, 19, 36, 41)));
|
||||
jest.advanceTimersByTime(61 * 1000);
|
||||
expect(tree.find("time").text()).toBe("2 hours ago");
|
||||
act(() => jest.advanceTimersByTime(31 * 1000));
|
||||
expect(
|
||||
tree
|
||||
.find("span.components-label.badge.badge-secondary.cursor-pointer")
|
||||
.at(0)
|
||||
.text()
|
||||
).toBe("2 hours ago");
|
||||
|
||||
advanceTo(new Date(Date.UTC(2018, 7, 16, 19, 36, 41)));
|
||||
act(() => jest.advanceTimersByTime(31 * 1000));
|
||||
expect(
|
||||
tree
|
||||
.find("span.components-label.badge.badge-secondary.cursor-pointer")
|
||||
.at(0)
|
||||
.text()
|
||||
).toBe("2 days ago");
|
||||
});
|
||||
});
|
||||
|
||||
+1
-4
@@ -285,10 +285,7 @@ exports[`<GroupFooter /> mathes snapshot when silence is rendered 1`] = `
|
||||
— me@example.com
|
||||
</span>
|
||||
<span class=\\"badge badge-danger align-text-bottom p-1\\">
|
||||
Expired
|
||||
<time datetime=\\"946688400000\\">
|
||||
14 hours ago
|
||||
</time>
|
||||
Expired 14 hours ago
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { mount } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import moment from "moment";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import {
|
||||
@@ -48,7 +47,7 @@ beforeEach(() => {
|
||||
alertStore = new AlertStore([]);
|
||||
silenceFormStore = new SilenceFormStore();
|
||||
group = MockGroup();
|
||||
advanceTo(moment.utc([2000, 0, 1, 15, 0, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 15, 0, 0)));
|
||||
|
||||
alertStore.data.receivers = ["by-cluster-service", "by-name"];
|
||||
});
|
||||
|
||||
@@ -3,8 +3,6 @@ import { act } from "react-dom/test-utils";
|
||||
|
||||
import { mount } from "enzyme";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import { MockAlert, MockAlertGroup } from "__mocks__/Alerts";
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
@@ -52,9 +50,9 @@ afterEach(() => {
|
||||
const MockAlerts = (alertCount) => {
|
||||
for (let i = 1; i <= alertCount; i++) {
|
||||
let alert = MockAlert([], { instance: `instance${i}` }, "active");
|
||||
const startsAt = moment().toISOString();
|
||||
alert.startsAt = startsAt;
|
||||
alert.alertmanager[0].startsAt = startsAt;
|
||||
const startsAt = new Date();
|
||||
alert.startsAt = startsAt.toISOString();
|
||||
alert.alertmanager[0].startsAt = startsAt.toISOString();
|
||||
group.alerts.push(alert);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,8 +5,6 @@ import { mount } from "enzyme";
|
||||
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import { EmptyAPIResponse } from "__mocks__/Fetch";
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
import { PressKey } from "__mocks__/PressKey";
|
||||
@@ -22,7 +20,7 @@ let cluster;
|
||||
let silence;
|
||||
|
||||
beforeEach(() => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 0)));
|
||||
jest.useFakeTimers();
|
||||
|
||||
alertStore = new AlertStore([]);
|
||||
@@ -297,7 +295,7 @@ describe("<DeleteSilenceModalContent />", () => {
|
||||
tree.find(".btn-danger").simulate("click");
|
||||
expect(useFetchDelete).toHaveBeenCalledTimes(1);
|
||||
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 1]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 1)));
|
||||
tree.find(".btn-danger").simulate("click");
|
||||
expect(useFetchDelete).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import moment from "moment";
|
||||
import Moment from "react-moment";
|
||||
import parseISO from "date-fns/parseISO";
|
||||
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
@@ -22,6 +21,7 @@ import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { QueryOperators } from "Common/Query";
|
||||
import { TooltipWrapper } from "Components/TooltipWrapper";
|
||||
import { RenderLinkAnnotation } from "Components/Grid/AlertGrid/AlertGroup/Annotation";
|
||||
import { DateFromNow } from "Components/DateFromNow";
|
||||
import { DeleteSilence } from "./DeleteSilence";
|
||||
|
||||
const SilenceIDCopyButton = ({ id }) => {
|
||||
@@ -51,7 +51,7 @@ const SilenceDetails = ({
|
||||
onEditSilence,
|
||||
isUpper,
|
||||
}) => {
|
||||
let isExpired = moment(silence.endsAt) < moment();
|
||||
const isExpired = parseISO(silence.endsAt) < new Date();
|
||||
let expiresClass = "";
|
||||
let expiresLabel = "Expires";
|
||||
if (isExpired) {
|
||||
@@ -78,7 +78,7 @@ const SilenceDetails = ({
|
||||
icon={faCalendarCheck}
|
||||
fixedWidth
|
||||
/>
|
||||
Started <Moment fromNow>{silence.startsAt}</Moment>
|
||||
Started <DateFromNow timestamp={silence.startsAt} />
|
||||
</span>
|
||||
<span
|
||||
className={`badge ${expiresClass} px-1 mr-1 components-label`}
|
||||
@@ -88,7 +88,7 @@ const SilenceDetails = ({
|
||||
icon={faCalendarTimes}
|
||||
fixedWidth
|
||||
/>
|
||||
{expiresLabel} <Moment fromNow>{silence.endsAt}</Moment>
|
||||
{expiresLabel} <DateFromNow timestamp={silence.endsAt} />
|
||||
</span>
|
||||
</div>
|
||||
<div className="my-1 d-flex flex-row">
|
||||
|
||||
@@ -6,7 +6,6 @@ import toDiffableHtml from "diffable-html";
|
||||
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
import moment from "moment";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
@@ -67,14 +66,14 @@ const MountedSilenceDetails = () => {
|
||||
|
||||
describe("<SilenceDetails />", () => {
|
||||
it("unexpired silence endsAt label doesn't use 'danger' class", () => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 0)));
|
||||
const tree = MountedSilenceDetails();
|
||||
const endsAt = tree.find("span.badge").at(1);
|
||||
expect(toDiffableHtml(endsAt.html())).not.toMatch(/text-danger/);
|
||||
});
|
||||
|
||||
it("expired silence endsAt label uses 'danger' class", () => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 23, 0, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 23, 0, 0)));
|
||||
const tree = MountedSilenceDetails();
|
||||
const endsAt = tree.find("span.badge").at(1);
|
||||
expect(toDiffableHtml(endsAt.html())).toMatch(/text-danger/);
|
||||
|
||||
@@ -2,16 +2,19 @@ import React, { useEffect, useState } from "react";
|
||||
|
||||
import { useObserver } from "mobx-react-lite";
|
||||
|
||||
import moment from "moment";
|
||||
import Moment from "react-moment";
|
||||
import parseISO from "date-fns/parseISO";
|
||||
import getUnixTime from "date-fns/getUnixTime";
|
||||
|
||||
import { APISilence } from "Models/API";
|
||||
import { DateFromNow } from "Components/DateFromNow";
|
||||
|
||||
import "./SilenceProgress.scss";
|
||||
|
||||
const calculatePercent = (startsAt, endsAt) => {
|
||||
const durationDone = moment().unix() - moment(startsAt).unix();
|
||||
const durationTotal = moment(endsAt).unix() - moment(startsAt).unix();
|
||||
const durationDone =
|
||||
getUnixTime(new Date()) - getUnixTime(parseISO(startsAt));
|
||||
const durationTotal =
|
||||
getUnixTime(parseISO(endsAt)) - getUnixTime(parseISO(startsAt));
|
||||
return Math.floor((durationDone / durationTotal) * 100);
|
||||
};
|
||||
|
||||
@@ -28,13 +31,13 @@ const SilenceProgress = ({ silence }) => {
|
||||
}, [silence.startsAt, silence.endsAt]);
|
||||
|
||||
return useObserver(() =>
|
||||
moment(silence.endsAt) < moment() ? (
|
||||
parseISO(silence.endsAt) < new Date() ? (
|
||||
<span className="badge badge-danger align-text-bottom p-1">
|
||||
Expired <Moment fromNow>{silence.endsAt}</Moment>
|
||||
Expired <DateFromNow timestamp={silence.endsAt} />
|
||||
</span>
|
||||
) : (
|
||||
<span className="badge badge-light nmb-05 align-text-bottom p-1">
|
||||
Expires <Moment fromNow>{silence.endsAt}</Moment>
|
||||
Expires <DateFromNow timestamp={silence.endsAt} />
|
||||
<div className="progress silence-progress">
|
||||
<div
|
||||
className={
|
||||
|
||||
@@ -5,7 +5,6 @@ import { mount } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import moment from "moment";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
@@ -35,40 +34,40 @@ const MountedSilenceProgress = () => {
|
||||
|
||||
describe("<SilenceProgress />", () => {
|
||||
it("renders with class 'danger' and no progressbar when expired", () => {
|
||||
advanceTo(moment.utc([2001, 0, 1, 23, 0, 0]));
|
||||
advanceTo(new Date(Date.UTC(2001, 0, 1, 23, 0, 0)));
|
||||
const tree = MountedSilenceProgress();
|
||||
expect(toDiffableHtml(tree.html())).toMatch(/badge-danger/);
|
||||
expect(tree.text()).toMatch(/Expired a year ago/);
|
||||
expect(tree.text()).toMatch(/Expired 1 year ago/);
|
||||
});
|
||||
|
||||
it("progressbar uses class 'danger' when > 90%", () => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 55, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 55, 0)));
|
||||
const tree = MountedSilenceProgress();
|
||||
expect(toDiffableHtml(tree.html())).toMatch(/progress-bar bg-danger/);
|
||||
});
|
||||
|
||||
it("progressbar uses class 'danger' when > 75%", () => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 50, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 50, 0)));
|
||||
const tree = MountedSilenceProgress();
|
||||
expect(toDiffableHtml(tree.html())).toMatch(/progress-bar bg-warning/);
|
||||
});
|
||||
|
||||
it("progressbar uses class 'success' when <= 75%", () => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 0)));
|
||||
const tree = MountedSilenceProgress();
|
||||
expect(toDiffableHtml(tree.html())).toMatch(/progress-bar bg-success/);
|
||||
});
|
||||
|
||||
it("progressbar is updated every 30 seconds", () => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 0)));
|
||||
const tree = MountedSilenceProgress();
|
||||
expect(toDiffableHtml(tree.html())).toMatch(/progress-bar bg-success/);
|
||||
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 50, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 50, 0)));
|
||||
act(() => jest.runOnlyPendingTimers());
|
||||
expect(toDiffableHtml(tree.html())).toMatch(/progress-bar bg-warning/);
|
||||
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 55, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 55, 0)));
|
||||
act(() => jest.runOnlyPendingTimers());
|
||||
expect(toDiffableHtml(tree.html())).toMatch(/progress-bar bg-danger/);
|
||||
});
|
||||
|
||||
@@ -28,10 +28,7 @@ exports[`<SilenceComment /> Matches snapshot when collapsed 1`] = `
|
||||
— me@example.com
|
||||
</span>
|
||||
<span class=\\"badge badge-danger align-text-bottom p-1\\">
|
||||
Expired
|
||||
<time datetime=\\"946688400000\\">
|
||||
20 years ago
|
||||
</time>
|
||||
Expired 20 years ago
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,10 +95,7 @@ exports[`<SilenceComment /> Matches snapshot when collapsed and multiple cluster
|
||||
ha
|
||||
</span>
|
||||
<span class=\\"badge badge-danger align-text-bottom p-1\\">
|
||||
Expired
|
||||
<time datetime=\\"946688400000\\">
|
||||
20 years ago
|
||||
</time>
|
||||
Expired 20 years ago
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,10 +32,7 @@ exports[`<ManagedSilence /> matches snapshot when collapsed 1`] = `
|
||||
— me@example.com
|
||||
</span>
|
||||
<span class=\\"badge badge-light nmb-05 align-text-bottom p-1\\">
|
||||
Expires
|
||||
<time datetime=\\"946688400000\\">
|
||||
in 30 minutes
|
||||
</time>
|
||||
Expires in 30 minutes
|
||||
<div class=\\"progress silence-progress\\">
|
||||
<div class=\\"progress-bar bg-success\\"
|
||||
role=\\"progressbar\\"
|
||||
@@ -166,10 +163,7 @@ exports[`<ManagedSilence /> matches snapshot with expaned details 1`] = `
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
Started
|
||||
<time datetime=\\"946684800000\\">
|
||||
30 minutes ago
|
||||
</time>
|
||||
Started 30 minutes ago
|
||||
</span>
|
||||
<span class=\\"badge px-1 mr-1 components-label\\">
|
||||
<svg aria-hidden=\\"true\\"
|
||||
@@ -186,10 +180,7 @@ exports[`<ManagedSilence /> matches snapshot with expaned details 1`] = `
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
Expires
|
||||
<time datetime=\\"946688400000\\">
|
||||
in 30 minutes
|
||||
</time>
|
||||
Expires in 30 minutes
|
||||
</span>
|
||||
</div>
|
||||
<div class=\\"my-1 d-flex flex-row\\">
|
||||
|
||||
@@ -4,7 +4,6 @@ import { mount } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import moment from "moment";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
@@ -20,7 +19,7 @@ let cluster;
|
||||
let silence;
|
||||
|
||||
beforeEach(() => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 0)));
|
||||
|
||||
alertStore = new AlertStore([]);
|
||||
silenceFormStore = new SilenceFormStore();
|
||||
@@ -169,7 +168,7 @@ describe("<ManagedSilence />", () => {
|
||||
});
|
||||
|
||||
it("shows Recreate button on expired silence", () => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 23, 30, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 23, 30, 0)));
|
||||
const tree = MountedManagedSilence();
|
||||
tree.find("svg.text-muted.cursor-pointer").simulate("click");
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import Moment from "react-moment";
|
||||
|
||||
export function MomentPolledTimer() {
|
||||
useEffect(() => {
|
||||
Moment.startPooledTimer();
|
||||
return () => Moment.clearPooledTimer();
|
||||
}, []);
|
||||
|
||||
return <span id="moment-polled-timer" />;
|
||||
}
|
||||
@@ -3,8 +3,6 @@ import { act } from "react-dom/test-utils";
|
||||
|
||||
import { mount } from "enzyme";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import { MockThemeContext } from "__mocks__/Theme";
|
||||
import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
@@ -26,8 +24,8 @@ beforeEach(() => {
|
||||
silenceFormStore = new SilenceFormStore();
|
||||
settingsStore.filterBarConfig.config.autohide = true;
|
||||
// fix startsAt & endsAt dates so they don't change between tests
|
||||
silenceFormStore.data.startsAt = moment([2018, 1, 30, 10, 25, 50]).utc();
|
||||
silenceFormStore.data.endsAt = moment([2018, 1, 30, 11, 25, 50]).utc();
|
||||
silenceFormStore.data.startsAt = new Date(Date.UTC(2018, 1, 30, 10, 25, 50));
|
||||
silenceFormStore.data.endsAt = new Date(Date.UTC(2018, 1, 30, 11, 25, 50));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -5,7 +5,6 @@ import { mount } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import moment from "moment";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
@@ -25,7 +24,7 @@ let cluster;
|
||||
let silence;
|
||||
|
||||
beforeEach(() => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 0]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 0)));
|
||||
jest.useFakeTimers();
|
||||
|
||||
alertStore = new AlertStore([]);
|
||||
@@ -108,13 +107,13 @@ describe("<Browser />", () => {
|
||||
settingsStore.fetchConfig.config.interval = 1;
|
||||
MountedBrowser();
|
||||
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 2]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 2)));
|
||||
act(() => jest.runOnlyPendingTimers());
|
||||
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 4]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 4)));
|
||||
act(() => jest.runOnlyPendingTimers());
|
||||
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 6]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 6)));
|
||||
act(() => jest.runOnlyPendingTimers());
|
||||
|
||||
expect(useFetchGet.fetch.calls).toHaveLength(4);
|
||||
@@ -364,7 +363,7 @@ describe("<Browser />", () => {
|
||||
tree.unmount();
|
||||
|
||||
act(() => {
|
||||
advanceTo(moment.utc([2000, 0, 1, 0, 30, 59]));
|
||||
advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 59)));
|
||||
jest.runOnlyPendingTimers();
|
||||
});
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ import PropTypes from "prop-types";
|
||||
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleUp } from "@fortawesome/free-solid-svg-icons/faAngleUp";
|
||||
import { faAngleDown } from "@fortawesome/free-solid-svg-icons/faAngleDown";
|
||||
@@ -59,8 +57,8 @@ const HourMinute = observer(
|
||||
}
|
||||
};
|
||||
|
||||
const hour = dateValue.hour();
|
||||
const minute = dateValue.minute();
|
||||
const hour = dateValue.getHours();
|
||||
const minute = dateValue.getMinutes();
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -117,7 +115,7 @@ const HourMinute = observer(
|
||||
}
|
||||
);
|
||||
HourMinute.propTypes = {
|
||||
dateValue: PropTypes.instanceOf(moment).isRequired,
|
||||
dateValue: PropTypes.instanceOf(Date).isRequired,
|
||||
onHourInc: PropTypes.func.isRequired,
|
||||
onHourDec: PropTypes.func.isRequired,
|
||||
onMinuteInc: PropTypes.func.isRequired,
|
||||
|
||||
@@ -3,7 +3,10 @@ import PropTypes from "prop-types";
|
||||
|
||||
import { useObserver } from "mobx-react-lite";
|
||||
|
||||
import moment from "moment";
|
||||
import differenceInMinutes from "date-fns/differenceInMinutes";
|
||||
import differenceInHours from "date-fns/differenceInHours";
|
||||
import differenceInDays from "date-fns/differenceInDays";
|
||||
import setSeconds from "date-fns/setSeconds";
|
||||
|
||||
import DayPicker from "react-day-picker";
|
||||
import "react-day-picker/lib/style.css";
|
||||
@@ -12,10 +15,16 @@ import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { Duration } from "./Duration";
|
||||
import { HourMinute } from "./HourMinute";
|
||||
|
||||
const nowZeroSeconds = () => {
|
||||
const now = new Date();
|
||||
now.setSeconds(0);
|
||||
return now;
|
||||
};
|
||||
|
||||
const OffsetBadge = ({ startDate, endDate, prefixLabel }) => {
|
||||
const days = endDate.diff(startDate, "days");
|
||||
const hours = endDate.diff(startDate, "hours") % 24;
|
||||
const minutes = endDate.diff(startDate, "minutes") % 60;
|
||||
const days = differenceInDays(endDate, startDate);
|
||||
const hours = differenceInHours(endDate, startDate) % 24;
|
||||
const minutes = differenceInMinutes(endDate, startDate) % 60;
|
||||
|
||||
return (
|
||||
<span className="badge badge-light">
|
||||
@@ -27,8 +36,8 @@ const OffsetBadge = ({ startDate, endDate, prefixLabel }) => {
|
||||
);
|
||||
};
|
||||
OffsetBadge.propTypes = {
|
||||
startDate: PropTypes.instanceOf(moment).isRequired,
|
||||
endDate: PropTypes.instanceOf(moment).isRequired,
|
||||
startDate: PropTypes.instanceOf(Date).isRequired,
|
||||
endDate: PropTypes.instanceOf(Date).isRequired,
|
||||
prefixLabel: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
@@ -60,28 +69,26 @@ const TabContentStart = ({ silenceFormStore }) => {
|
||||
<div className="d-flex justify-content-center align-items-center">
|
||||
<DayPicker
|
||||
className="components-date-range"
|
||||
month={silenceFormStore.data.startsAt.toDate()}
|
||||
month={silenceFormStore.data.startsAt}
|
||||
disabledDays={{
|
||||
before: moment().second(0).toDate(),
|
||||
before: nowZeroSeconds(),
|
||||
}}
|
||||
todayButton="Today"
|
||||
onDayClick={(val, ...mod) => {
|
||||
const startsAt = moment(val);
|
||||
startsAt.set({
|
||||
hour: silenceFormStore.data.startsAt.hour(),
|
||||
minute: silenceFormStore.data.startsAt.minute(),
|
||||
second: 0,
|
||||
});
|
||||
const startsAt = new Date(val);
|
||||
startsAt.setHours(silenceFormStore.data.startsAt.getHours());
|
||||
startsAt.setMinutes(silenceFormStore.data.startsAt.getMinutes());
|
||||
startsAt.setSeconds(0);
|
||||
silenceFormStore.data.startsAt = startsAt;
|
||||
silenceFormStore.data.verifyStarEnd();
|
||||
}}
|
||||
selectedDays={{
|
||||
from: silenceFormStore.data.startsAt.toDate(),
|
||||
to: silenceFormStore.data.endsAt.toDate(),
|
||||
from: silenceFormStore.data.startsAt,
|
||||
to: silenceFormStore.data.endsAt,
|
||||
}}
|
||||
modifiers={{
|
||||
start: silenceFormStore.data.startsAt.toDate(),
|
||||
end: silenceFormStore.data.endsAt.toDate(),
|
||||
start: silenceFormStore.data.startsAt,
|
||||
end: silenceFormStore.data.endsAt,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -102,28 +109,26 @@ const TabContentEnd = ({ silenceFormStore }) => {
|
||||
<div className="d-flex justify-content-center align-items-center">
|
||||
<DayPicker
|
||||
className="components-date-range"
|
||||
month={silenceFormStore.data.endsAt.toDate()}
|
||||
month={silenceFormStore.data.endsAt}
|
||||
disabledDays={{
|
||||
before: silenceFormStore.data.startsAt.second(0).toDate(),
|
||||
before: setSeconds(silenceFormStore.data.startsAt, 0),
|
||||
}}
|
||||
todayButton="Today"
|
||||
onDayClick={(val) => {
|
||||
const endsAt = moment(val);
|
||||
endsAt.set({
|
||||
hour: silenceFormStore.data.endsAt.hour(),
|
||||
minute: silenceFormStore.data.endsAt.minute(),
|
||||
second: 0,
|
||||
});
|
||||
const endsAt = new Date(val);
|
||||
endsAt.setHours(silenceFormStore.data.endsAt.getHours());
|
||||
endsAt.setMinutes(silenceFormStore.data.endsAt.getMinutes());
|
||||
endsAt.setSeconds(0);
|
||||
silenceFormStore.data.endsAt = endsAt;
|
||||
silenceFormStore.data.verifyStarEnd();
|
||||
}}
|
||||
selectedDays={{
|
||||
from: silenceFormStore.data.startsAt.toDate(),
|
||||
to: silenceFormStore.data.endsAt.toDate(),
|
||||
from: silenceFormStore.data.startsAt,
|
||||
to: silenceFormStore.data.endsAt,
|
||||
}}
|
||||
modifiers={{
|
||||
start: silenceFormStore.data.startsAt.toDate(),
|
||||
end: silenceFormStore.data.endsAt.toDate(),
|
||||
start: silenceFormStore.data.startsAt,
|
||||
end: silenceFormStore.data.endsAt,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -199,10 +204,10 @@ TabContentDuration.propTypes = {
|
||||
|
||||
const DateTimeSelect = ({ silenceFormStore, openTab }) => {
|
||||
const [currentTab, setCurrentTab] = useState(openTab);
|
||||
const [timeNow, setTimeNow] = useState(moment().seconds(0));
|
||||
const [timeNow, setTimeNow] = useState(nowZeroSeconds());
|
||||
|
||||
const updateTimeNow = useCallback(() => {
|
||||
setTimeNow(moment().seconds(0));
|
||||
setTimeNow(nowZeroSeconds());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -7,7 +7,9 @@ import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import moment from "moment";
|
||||
import addMinutes from "date-fns/addMinutes";
|
||||
import addHours from "date-fns/addHours";
|
||||
import differenceInMilliseconds from "date-fns/differenceInMilliseconds";
|
||||
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import {
|
||||
@@ -21,8 +23,8 @@ let silenceFormStore;
|
||||
|
||||
beforeEach(() => {
|
||||
silenceFormStore = new SilenceFormStore();
|
||||
silenceFormStore.data.startsAt = moment([2060, 1, 1, 0, 0, 0]);
|
||||
silenceFormStore.data.endsAt = moment([2061, 1, 1, 0, 0, 0]);
|
||||
silenceFormStore.data.startsAt = new Date(2060, 1, 1, 0, 0, 0);
|
||||
silenceFormStore.data.endsAt = new Date(2061, 1, 1, 0, 0, 0);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -121,8 +123,8 @@ describe("<DateTimeSelect />", () => {
|
||||
it("'Ends' tab offset badge is updated after 1 minute", () => {
|
||||
jest.useFakeTimers();
|
||||
advanceTo(new Date(2060, 1, 1, 12, 0, 0));
|
||||
silenceFormStore.data.startsAt = moment([2060, 1, 1, 12, 0, 0]);
|
||||
silenceFormStore.data.endsAt = moment([2060, 1, 1, 13, 0, 0]);
|
||||
silenceFormStore.data.startsAt = new Date(2060, 1, 1, 12, 0, 0);
|
||||
silenceFormStore.data.endsAt = new Date(2060, 1, 1, 13, 0, 0);
|
||||
|
||||
const tree = MountedDateTimeSelect();
|
||||
expect(tree.find(".nav-link").at(1).text()).toBe("Endsin 1h ");
|
||||
@@ -149,19 +151,22 @@ const ValidateTimeButton = (
|
||||
const button = tab.find("td > span").at(elemIndex);
|
||||
expect(button.html()).toMatch(iconMatch);
|
||||
|
||||
const oldTimeValue = moment(silenceFormStore.data[storeKey]);
|
||||
const oldTimeValue = new Date(silenceFormStore.data[storeKey]);
|
||||
button.simulate("click");
|
||||
expect(silenceFormStore.data[storeKey].toISOString()).not.toBe(
|
||||
oldTimeValue.toISOString()
|
||||
);
|
||||
const diffMS = silenceFormStore.data[storeKey].diff(oldTimeValue);
|
||||
const diffMS = differenceInMilliseconds(
|
||||
silenceFormStore.data[storeKey],
|
||||
oldTimeValue
|
||||
);
|
||||
expect(diffMS).toBe(expectedDiff);
|
||||
};
|
||||
|
||||
const ValidateTimeWheel = (tab, storeKey, className, deltaY, expectedDiff) => {
|
||||
const elem = tab.find(className);
|
||||
|
||||
const oldTimeValue = moment(silenceFormStore.data[storeKey]);
|
||||
const oldTimeValue = new Date(silenceFormStore.data[storeKey]);
|
||||
|
||||
elem.simulate("wheel", { deltaY: deltaY });
|
||||
// fire real event so cancel listener will trigger
|
||||
@@ -175,7 +180,10 @@ const ValidateTimeWheel = (tab, storeKey, className, deltaY, expectedDiff) => {
|
||||
expect(silenceFormStore.data[storeKey].toISOString()).not.toBe(
|
||||
oldTimeValue.toISOString()
|
||||
);
|
||||
const diffMS = silenceFormStore.data[storeKey].diff(oldTimeValue);
|
||||
const diffMS = differenceInMilliseconds(
|
||||
silenceFormStore.data[storeKey],
|
||||
oldTimeValue
|
||||
);
|
||||
expect(diffMS).toBe(expectedDiff);
|
||||
};
|
||||
|
||||
@@ -187,11 +195,11 @@ describe("<TabContentStart />", () => {
|
||||
it("selecting date on DayPicker updates startsAt", () => {
|
||||
const tree = MountedTabContentStart();
|
||||
expect(silenceFormStore.data.startsAt.toISOString()).toBe(
|
||||
moment([2060, 1, 1, 0, 0, 0]).toISOString()
|
||||
new Date(2060, 1, 1, 0, 0, 0).toISOString()
|
||||
);
|
||||
tree.find('div[aria-label="Wed Feb 18 2060"]').simulate("click");
|
||||
expect(silenceFormStore.data.startsAt.toISOString()).toBe(
|
||||
moment([2060, 1, 18, 0, 0, 0]).toISOString()
|
||||
new Date(2060, 1, 18, 0, 0, 0).toISOString()
|
||||
);
|
||||
});
|
||||
|
||||
@@ -300,11 +308,11 @@ describe("<TabContentEnd />", () => {
|
||||
it("Selecting date on DayPicker updates endsAt", () => {
|
||||
const tree = MountedTabContentEnd();
|
||||
expect(silenceFormStore.data.endsAt.toISOString()).toBe(
|
||||
moment([2061, 1, 1, 0, 0, 0]).toISOString()
|
||||
new Date(2061, 1, 1, 0, 0, 0).toISOString()
|
||||
);
|
||||
tree.find('div[aria-label="Thu Feb 24 2061"]').simulate("click");
|
||||
expect(silenceFormStore.data.endsAt.toISOString()).toBe(
|
||||
moment([2061, 1, 24, 0, 0, 0]).toISOString()
|
||||
new Date(2061, 1, 24, 0, 0, 0).toISOString()
|
||||
);
|
||||
});
|
||||
|
||||
@@ -406,12 +414,15 @@ const ValidateDurationButton = (elemIndex, iconMatch, expectedDiff) => {
|
||||
const button = tree.find("td > span").at(elemIndex);
|
||||
expect(button.html()).toMatch(iconMatch);
|
||||
|
||||
const oldEndsAt = moment(silenceFormStore.data.endsAt);
|
||||
const oldEndsAt = new Date(silenceFormStore.data.endsAt);
|
||||
button.simulate("click");
|
||||
expect(silenceFormStore.data.endsAt.toISOString()).not.toBe(
|
||||
oldEndsAt.toISOString()
|
||||
);
|
||||
const diffMS = silenceFormStore.data.endsAt.diff(oldEndsAt);
|
||||
const diffMS = differenceInMilliseconds(
|
||||
silenceFormStore.data.endsAt,
|
||||
oldEndsAt
|
||||
);
|
||||
expect(diffMS).toBe(expectedDiff);
|
||||
};
|
||||
|
||||
@@ -421,7 +432,7 @@ const ValidateDurationWheel = (elemIndex, deltaY, expectedDiff) => {
|
||||
);
|
||||
const elem = tree.find(".components-duration").at(elemIndex);
|
||||
|
||||
const oldEndsAt = moment(silenceFormStore.data.endsAt);
|
||||
const oldEndsAt = new Date(silenceFormStore.data.endsAt);
|
||||
|
||||
elem.simulate("wheel", { deltaY: deltaY });
|
||||
// fire real event so cancel listener will trigger
|
||||
@@ -431,7 +442,10 @@ const ValidateDurationWheel = (elemIndex, deltaY, expectedDiff) => {
|
||||
expect(silenceFormStore.data.endsAt.toISOString()).not.toBe(
|
||||
oldEndsAt.toISOString()
|
||||
);
|
||||
const diffMS = silenceFormStore.data.endsAt.diff(oldEndsAt);
|
||||
const diffMS = differenceInMilliseconds(
|
||||
silenceFormStore.data.endsAt,
|
||||
oldEndsAt
|
||||
);
|
||||
expect(diffMS).toBe(expectedDiff);
|
||||
};
|
||||
|
||||
@@ -486,8 +500,8 @@ describe("<TabContentDuration />", () => {
|
||||
});
|
||||
|
||||
const SetDurationTo = (hours, minutes) => {
|
||||
const startsAt = moment([2060, 1, 1, 0, 0, 0]);
|
||||
const endsAt = moment(startsAt).add(hours, "hours").add(minutes, "minutes");
|
||||
const startsAt = new Date(2060, 1, 1, 0, 0, 0);
|
||||
const endsAt = addMinutes(addHours(startsAt, hours), minutes);
|
||||
silenceFormStore.data.startsAt = startsAt;
|
||||
silenceFormStore.data.endsAt = endsAt;
|
||||
};
|
||||
|
||||
@@ -4,16 +4,14 @@ import { render } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import moment from "moment";
|
||||
|
||||
import { SilenceFormStore } from "Stores/SilenceFormStore";
|
||||
import { PayloadPreview } from ".";
|
||||
|
||||
describe("<PayloadPreview />", () => {
|
||||
it("matches snapshot", () => {
|
||||
const silenceFormStore = new SilenceFormStore();
|
||||
silenceFormStore.data.startsAt = moment.utc([2000, 1, 1, 0, 0, 0]);
|
||||
silenceFormStore.data.endsAt = moment.utc([2000, 1, 1, 1, 0, 0]);
|
||||
silenceFormStore.data.startsAt = new Date(Date.UTC(2000, 1, 1, 0, 0, 0));
|
||||
silenceFormStore.data.endsAt = new Date(Date.UTC(2000, 1, 1, 1, 0, 0));
|
||||
silenceFormStore.data.createdBy = "me@example.com";
|
||||
silenceFormStore.data.comment = "PayloadPreview test";
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import fetchMock from "fetch-mock";
|
||||
|
||||
import { storiesOf } from "@storybook/react";
|
||||
|
||||
import moment from "moment";
|
||||
import addHours from "date-fns/addHours";
|
||||
import addDays from "date-fns/addDays";
|
||||
|
||||
import { MockSilence } from "__mocks__/Alerts";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
@@ -105,8 +106,8 @@ storiesOf("SilenceModal", module)
|
||||
silenceFormStore.data.comment = "fake silence";
|
||||
|
||||
silenceFormStore.data.silenceID = "1234567890";
|
||||
silenceFormStore.data.startsAt = moment();
|
||||
silenceFormStore.data.endsAt = moment().add(2, "hour").add(10, "day");
|
||||
silenceFormStore.data.startsAt = new Date();
|
||||
silenceFormStore.data.endsAt = addDays(addHours(new Date(), 2), 10);
|
||||
|
||||
silenceFormStore.tab.current = SilenceTabNames.Editor;
|
||||
|
||||
|
||||
@@ -2,7 +2,13 @@ import { observable, action, computed } from "mobx";
|
||||
|
||||
import uniqueId from "lodash.uniqueid";
|
||||
|
||||
import moment from "moment";
|
||||
import parseISO from "date-fns/parseISO";
|
||||
import addHours from "date-fns/addHours";
|
||||
import addMinutes from "date-fns/addMinutes";
|
||||
import subMinutes from "date-fns/subMinutes";
|
||||
import differenceInDays from "date-fns/differenceInDays";
|
||||
import differenceInHours from "date-fns/differenceInHours";
|
||||
import differenceInMinutes from "date-fns/differenceInMinutes";
|
||||
|
||||
const NewEmptyMatcher = () => {
|
||||
return {
|
||||
@@ -178,8 +184,8 @@ class SilenceFormStore {
|
||||
silenceID: null,
|
||||
alertmanagers: [],
|
||||
matchers: [],
|
||||
startsAt: moment(),
|
||||
endsAt: moment().add(1, "hour"),
|
||||
startsAt: new Date(),
|
||||
endsAt: addHours(new Date(), 1),
|
||||
comment: "",
|
||||
author: "",
|
||||
|
||||
@@ -201,8 +207,8 @@ class SilenceFormStore {
|
||||
},
|
||||
|
||||
resetStartEnd() {
|
||||
this.startsAt = moment();
|
||||
this.endsAt = moment().add(1, "hour");
|
||||
this.startsAt = new Date();
|
||||
this.endsAt = addHours(new Date(), 1);
|
||||
},
|
||||
|
||||
resetProgress() {
|
||||
@@ -260,44 +266,51 @@ class SilenceFormStore {
|
||||
}
|
||||
this.matchers = matchers;
|
||||
|
||||
this.startsAt = moment(silence.startsAt);
|
||||
this.endsAt = moment(silence.endsAt);
|
||||
this.startsAt = parseISO(silence.startsAt);
|
||||
this.endsAt = parseISO(silence.endsAt);
|
||||
this.comment = silence.comment;
|
||||
this.author = silence.createdBy;
|
||||
},
|
||||
|
||||
verifyStarEnd() {
|
||||
const now = moment().second(0);
|
||||
if (this.startsAt.isBefore(now)) {
|
||||
const now = new Date();
|
||||
now.setSeconds(0);
|
||||
if (this.startsAt < now) {
|
||||
this.startsAt = now;
|
||||
}
|
||||
|
||||
if (this.endsAt.isSameOrBefore(this.startsAt)) {
|
||||
this.endsAt = moment(this.startsAt).add(1, "minutes");
|
||||
if (this.endsAt <= this.startsAt) {
|
||||
this.endsAt = addMinutes(this.startsAt, 1);
|
||||
}
|
||||
},
|
||||
incStart(minutes) {
|
||||
this.startsAt = moment(this.startsAt).add(minutes, "minutes");
|
||||
this.startsAt = addMinutes(this.startsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decStart(minutes) {
|
||||
this.startsAt = moment(this.startsAt).subtract(minutes, "minutes");
|
||||
this.startsAt = subMinutes(this.startsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
incEnd(minutes) {
|
||||
this.endsAt = moment(this.endsAt).add(minutes, "minutes");
|
||||
this.endsAt = addMinutes(this.endsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
decEnd(minutes) {
|
||||
this.endsAt = moment(this.endsAt).subtract(minutes, "minutes");
|
||||
this.endsAt = subMinutes(this.endsAt, minutes);
|
||||
this.verifyStarEnd();
|
||||
},
|
||||
|
||||
get toAlertmanagerPayload() {
|
||||
const startsAt = new Date(this.startsAt);
|
||||
startsAt.setSeconds(0);
|
||||
startsAt.setMilliseconds(0);
|
||||
const endsAt = new Date(this.endsAt);
|
||||
endsAt.setSeconds(0);
|
||||
endsAt.setMilliseconds(0);
|
||||
return GenerateAlertmanagerSilenceData(
|
||||
this.startsAt.second(0).millisecond(0),
|
||||
this.endsAt.second(0).millisecond(0),
|
||||
startsAt,
|
||||
endsAt,
|
||||
this.matchers,
|
||||
this.author,
|
||||
this.comment,
|
||||
@@ -307,9 +320,9 @@ class SilenceFormStore {
|
||||
|
||||
get toDuration() {
|
||||
const data = {
|
||||
days: this.endsAt.diff(this.startsAt, "days"),
|
||||
hours: this.endsAt.diff(this.startsAt, "hours") % 24,
|
||||
minutes: this.endsAt.diff(this.startsAt, "minutes") % 60,
|
||||
days: differenceInDays(this.endsAt, this.startsAt),
|
||||
hours: differenceInHours(this.endsAt, this.startsAt) % 24,
|
||||
minutes: differenceInMinutes(this.endsAt, this.startsAt) % 60,
|
||||
};
|
||||
return data;
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import moment from "moment";
|
||||
import differenceInMilliseconds from "date-fns/differenceInMilliseconds";
|
||||
import isSameDay from "date-fns/isSameDay";
|
||||
|
||||
import {
|
||||
MockAlert,
|
||||
@@ -74,13 +75,13 @@ describe("SilenceFormStore.toggle", () => {
|
||||
|
||||
describe("SilenceFormStore.data", () => {
|
||||
it("resetStartEnd() sets startsAt and endsAt to defaults", () => {
|
||||
store.data.startsAt = moment([2000, 1, 1, 0, 1, 0]);
|
||||
store.data.endsAt = moment([2000, 1, 1, 1, 2, 0]);
|
||||
expect(store.data.startsAt.isSame([2000, 1, 1], "day")).toBe(true);
|
||||
expect(store.data.endsAt.isSame([2000, 1, 1], "day")).toBe(true);
|
||||
store.data.startsAt = new Date(2000, 1, 1, 0, 1, 0);
|
||||
store.data.endsAt = new Date(2000, 1, 1, 1, 2, 0);
|
||||
expect(isSameDay(store.data.startsAt, new Date(2000, 1, 1))).toBe(true);
|
||||
expect(isSameDay(store.data.endsAt, new Date(2000, 1, 1))).toBe(true);
|
||||
store.data.resetStartEnd();
|
||||
expect(store.data.startsAt.isSame([2000, 1, 1], "day")).toBe(false);
|
||||
expect(store.data.endsAt.isSame([2000, 1, 1], "day")).toBe(false);
|
||||
expect(isSameDay(store.data.startsAt, new Date(2000, 1, 1))).toBe(false);
|
||||
expect(isSameDay(store.data.endsAt, new Date(2000, 1, 1))).toBe(false);
|
||||
});
|
||||
|
||||
it("resetProgress() sets currentStage to UserInput", () => {
|
||||
@@ -303,11 +304,11 @@ describe("SilenceFormStore.data", () => {
|
||||
})
|
||||
);
|
||||
|
||||
expect(store.data.startsAt.utc().toISOString()).toBe(
|
||||
moment.utc([2000, 0, 1, 0, 0, 0]).toISOString()
|
||||
expect(store.data.startsAt.toISOString()).toBe(
|
||||
new Date(Date.UTC(2000, 0, 1, 0, 0, 0)).toISOString()
|
||||
);
|
||||
expect(store.data.endsAt.utc().toISOString()).toBe(
|
||||
moment.utc([2000, 0, 1, 1, 0, 0]).toISOString()
|
||||
expect(store.data.endsAt.toISOString()).toBe(
|
||||
new Date(Date.UTC(2000, 0, 1, 1, 0, 0)).toISOString()
|
||||
);
|
||||
|
||||
expect(store.data.author).toBe("me@example.com");
|
||||
@@ -331,8 +332,8 @@ describe("SilenceFormStore.data", () => {
|
||||
store.data.fillMatchersFromGroup(group, []);
|
||||
// add empty matcher so we test empty string rendering
|
||||
store.data.addEmptyMatcher();
|
||||
store.data.startsAt = moment.utc([2000, 1, 1, 0, 0, 0]);
|
||||
store.data.endsAt = moment.utc([2000, 1, 1, 1, 0, 0]);
|
||||
store.data.startsAt = new Date(Date.UTC(2000, 1, 1, 0, 0, 0));
|
||||
store.data.endsAt = new Date(Date.UTC(2000, 1, 1, 1, 0, 0));
|
||||
store.data.author = "me@example.com";
|
||||
store.data.comment = "toAlertmanagerPayload test";
|
||||
expect(store.data.toAlertmanagerPayload).toMatchSnapshot();
|
||||
@@ -406,8 +407,8 @@ describe("SilenceFormStore.data.isValid", () => {
|
||||
|
||||
describe("SilenceFormStore.data startsAt & endsAt validation", () => {
|
||||
it("toDuration returns correct duration for 5d 0h 1m", () => {
|
||||
store.data.startsAt = moment([2000, 1, 1, 0, 0, 0]);
|
||||
store.data.endsAt = moment([2000, 1, 6, 0, 1, 15]);
|
||||
store.data.startsAt = new Date(2000, 1, 1, 0, 0, 0);
|
||||
store.data.endsAt = new Date(2000, 1, 6, 0, 1, 15);
|
||||
expect(store.data.toDuration).toMatchObject({
|
||||
days: 5,
|
||||
hours: 0,
|
||||
@@ -416,8 +417,8 @@ describe("SilenceFormStore.data startsAt & endsAt validation", () => {
|
||||
});
|
||||
|
||||
it("toDuration returns correct duration for 2h 15m", () => {
|
||||
store.data.startsAt = moment([2000, 1, 1, 0, 0, 0]);
|
||||
store.data.endsAt = moment([2000, 1, 1, 2, 15, 0]);
|
||||
store.data.startsAt = new Date(2000, 1, 1, 0, 0, 0);
|
||||
store.data.endsAt = new Date(2000, 1, 1, 2, 15, 0);
|
||||
expect(store.data.toDuration).toMatchObject({
|
||||
days: 0,
|
||||
hours: 2,
|
||||
@@ -426,8 +427,8 @@ describe("SilenceFormStore.data startsAt & endsAt validation", () => {
|
||||
});
|
||||
|
||||
it("toDuration returns correct duration for 59m", () => {
|
||||
store.data.startsAt = moment([2000, 1, 1, 0, 10, 0]);
|
||||
store.data.endsAt = moment([2000, 1, 1, 1, 9, 0]);
|
||||
store.data.startsAt = new Date(2000, 1, 1, 0, 10, 0);
|
||||
store.data.endsAt = new Date(2000, 1, 1, 1, 9, 0);
|
||||
expect(store.data.toDuration).toMatchObject({
|
||||
days: 0,
|
||||
hours: 0,
|
||||
@@ -436,8 +437,8 @@ describe("SilenceFormStore.data startsAt & endsAt validation", () => {
|
||||
});
|
||||
|
||||
it("verifyStarEnd() doesn't do anything if endsAt if after startsAt", () => {
|
||||
const startsAt = moment([2063, 1, 1, 0, 0, 0]);
|
||||
const endsAt = moment([2063, 1, 1, 1, 1, 0]);
|
||||
const startsAt = new Date(2063, 1, 1, 0, 0, 0);
|
||||
const endsAt = new Date(2063, 1, 1, 1, 1, 0);
|
||||
store.data.startsAt = startsAt;
|
||||
store.data.endsAt = endsAt;
|
||||
store.data.verifyStarEnd();
|
||||
@@ -446,57 +447,58 @@ describe("SilenceFormStore.data startsAt & endsAt validation", () => {
|
||||
});
|
||||
|
||||
it("verifyStarEnd() updates startsAt if it's before now()", () => {
|
||||
const now = moment().second(0);
|
||||
const startsAt = moment([2000, 1, 1, 0, 0, 1]);
|
||||
const endsAt = moment([2063, 1, 1, 0, 0, 0]);
|
||||
const now = new Date();
|
||||
now.setSeconds(0);
|
||||
const startsAt = new Date(2000, 1, 1, 0, 0, 1);
|
||||
const endsAt = new Date(2063, 1, 1, 0, 0, 0);
|
||||
store.data.startsAt = startsAt;
|
||||
store.data.endsAt = endsAt;
|
||||
store.data.verifyStarEnd();
|
||||
expect(store.data.startsAt.isSameOrAfter(now)).toBeTruthy();
|
||||
expect(store.data.startsAt >= now).toBeTruthy();
|
||||
expect(store.data.endsAt.toISOString()).toBe(endsAt.toISOString());
|
||||
});
|
||||
|
||||
it("verifyStarEnd() updates endsAt if it's before startsAt", () => {
|
||||
const startsAt = moment([2063, 1, 1, 0, 0, 1]);
|
||||
const endsAt = moment([2063, 1, 1, 0, 0, 0]);
|
||||
const startsAt = new Date(2063, 1, 1, 0, 0, 1);
|
||||
const endsAt = new Date(2063, 1, 1, 0, 0, 0);
|
||||
store.data.startsAt = startsAt;
|
||||
store.data.endsAt = endsAt;
|
||||
store.data.verifyStarEnd();
|
||||
expect(store.data.startsAt.toISOString()).toBe(startsAt.toISOString());
|
||||
expect(store.data.endsAt.toISOString()).toBe(
|
||||
moment([2063, 1, 1, 0, 1, 1]).toISOString()
|
||||
new Date(2063, 1, 1, 0, 1, 1).toISOString()
|
||||
);
|
||||
});
|
||||
|
||||
it("incStart(7) adds 7 minutes to startsAt", () => {
|
||||
const startsAt = moment([2063, 1, 1, 0, 0, 1]);
|
||||
const startsAt = new Date(2063, 1, 1, 0, 0, 1);
|
||||
store.data.startsAt = startsAt;
|
||||
store.data.incStart(7);
|
||||
const diffMS = store.data.startsAt.diff(startsAt);
|
||||
const diffMS = differenceInMilliseconds(store.data.startsAt, startsAt);
|
||||
expect(diffMS).toBe(7 * 60 * 1000);
|
||||
});
|
||||
|
||||
it("decStart(14) subtracts 14 minutes from startsAt", () => {
|
||||
const startsAt = moment([2063, 1, 1, 0, 0, 1]);
|
||||
const startsAt = new Date(2063, 1, 1, 0, 0, 1);
|
||||
store.data.startsAt = startsAt;
|
||||
store.data.decStart(14);
|
||||
const diffMS = store.data.startsAt.diff(startsAt);
|
||||
const diffMS = differenceInMilliseconds(store.data.startsAt, startsAt);
|
||||
expect(diffMS).toBe(-14 * 60 * 1000);
|
||||
});
|
||||
|
||||
it("incEnd(120) adds 120 minutes to endsAt", () => {
|
||||
const endsAt = moment([2063, 1, 1, 0, 0, 1]);
|
||||
const endsAt = new Date(2063, 1, 1, 0, 0, 1);
|
||||
store.data.endsAt = endsAt;
|
||||
store.data.incEnd(120);
|
||||
const diffMS = store.data.endsAt.diff(endsAt);
|
||||
const diffMS = differenceInMilliseconds(store.data.endsAt, endsAt);
|
||||
expect(diffMS).toBe(120 * 60 * 1000);
|
||||
});
|
||||
|
||||
it("decEnd(1) subtracts 1 minute from endsAt", () => {
|
||||
const endsAt = moment([2063, 1, 1, 0, 0, 1]);
|
||||
const endsAt = new Date(2063, 1, 1, 0, 0, 1);
|
||||
store.data.endsAt = endsAt;
|
||||
store.data.decEnd(1);
|
||||
const diffMS = store.data.endsAt.diff(endsAt);
|
||||
const diffMS = differenceInMilliseconds(store.data.endsAt, endsAt);
|
||||
expect(diffMS).toBe(-1 * 60 * 1000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import moment from "moment";
|
||||
|
||||
import { MockAlert, MockAlertGroup, MockSilence } from "./Alerts";
|
||||
|
||||
const EmptyAPIResponse = () => ({
|
||||
status: "success",
|
||||
timestamp: moment().toISOString(),
|
||||
timestamp: new Date().toISOString(),
|
||||
version: "fakeVersion",
|
||||
upstreams: {
|
||||
counters: { total: 1, healthy: 1, failed: 0 },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import moment from "moment";
|
||||
import subMinutes from "date-fns/subMinutes";
|
||||
|
||||
import { MockAlert, MockAlertGroup, MockSilence } from "./Alerts";
|
||||
|
||||
@@ -49,7 +49,7 @@ const MockGroup = (groupName, alertCount, active, suppressed, unprocessed) => {
|
||||
{ instance: `instance${i}` },
|
||||
state
|
||||
);
|
||||
alert.startsAt = moment().subtract(alertCount, "minutes").toISOString();
|
||||
alert.startsAt = subMinutes(new Date(), alertCount).toISOString();
|
||||
alerts.push(alert);
|
||||
}
|
||||
const group = MockAlertGroup(
|
||||
|
||||
Reference in New Issue
Block a user