feat(tests): add Silence component tests

This commit is contained in:
Łukasz Mierzwa
2018-09-01 19:36:01 +01:00
parent 1550025336
commit 4dfd044cc3
6 changed files with 358 additions and 1 deletions
+40
View File
@@ -3100,6 +3100,40 @@
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
},
"diffable-html": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/diffable-html/-/diffable-html-3.0.0.tgz",
"integrity": "sha512-lUxHiU00DexR/wKcY56OiJZmB0D66ghidYfU4VxUMG09TDx+1jjO7/dFrZKI2p9z00tWY/7ZeO9BBEi6n0jUYQ==",
"dev": true,
"requires": {
"htmlparser2": "3.9.2"
},
"dependencies": {
"domhandler": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
"dev": true,
"requires": {
"domelementtype": "1.3.0"
}
},
"htmlparser2": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
"integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
"dev": true,
"requires": {
"domelementtype": "1.3.0",
"domhandler": "2.4.2",
"domutils": "1.5.1",
"entities": "1.1.1",
"inherits": "2.0.3",
"readable-stream": "2.3.6"
}
}
}
},
"diffie-hellman": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@@ -6534,6 +6568,12 @@
"pretty-format": "20.0.3"
}
},
"jest-date-mock": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/jest-date-mock/-/jest-date-mock-1.0.3.tgz",
"integrity": "sha512-PLwqL0KI+zDKc6SoytvApudwFD8uDLOM7Bf4Z5C3KpJrHDJv5RawgSZUQOUqSukQ+TOhdHzliUOvGtE3aA+fWA==",
"dev": true
},
"jest-diff": {
"version": "20.0.3",
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-20.0.3.tgz",
+2
View File
@@ -51,11 +51,13 @@
"watch-css": "npm run build-css && node_modules/.bin/node-sass-chokidar src/ -o src/ --watch --recursive"
},
"devDependencies": {
"diffable-html": "3.0.0",
"enzyme": "3.5.0",
"enzyme-adapter-react-16": "1.3.1",
"enzyme-to-json": "3.3.4",
"eslint-plugin-react": "7.11.1",
"jest-canvas-mock": "1.1.0",
"jest-date-mock": "1.0.3",
"jest-fetch-mock": "1.6.5",
"jest-localstorage-mock": "2.2.0",
"jest-mock-console": "0.4.0",
@@ -0,0 +1,118 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Silence /> matches snapshot when data is not present in alertStore 1`] = `
"
<div>
<small class=\\"text-muted\\">
Silenced by default/4cf5fd82-1edd-4169-99d1-ff8415e72179
</small>
</div>
"
`;
exports[`<Silence /> matches snapshot when data is present in alertStore 1`] = `
"
<div class=\\"card mt-1 border-0 p-1\\">
<div class=\\"card-text mb-0\\">
<span class=\\"text-muted my-1\\">
Fake silence
<span class=\\"blockquote-footer pt-1\\">
<a class=\\"float-right cursor-pointer\\">
<svg aria-hidden=\\"true\\"
data-prefix=\\"fas\\"
data-icon=\\"chevron-up\\"
class=\\"svg-inline--fa fa-chevron-up fa-w-14 \\"
role=\\"img\\"
xmlns=\\"http://www.w3.org/2000/svg\\"
viewbox=\\"0 0 448 512\\"
>
<path fill=\\"currentColor\\"
d=\\"M240.971 130.524l194.343 194.343c9.373 9.373 9.373 24.569 0 33.941l-22.667 22.667c-9.357 9.357-24.522 9.375-33.901.04L224 227.495 69.255 381.516c-9.379 9.335-24.544 9.317-33.901-.04l-22.667-22.667c-9.373-9.373-9.373-24.569 0-33.941L207.03 130.525c9.372-9.373 24.568-9.373 33.941-.001z\\"
>
</path>
</svg>
</a>
<cite class=\\"components-grid-alertgroup-silences mr-2\\">
me@example.com
</cite>
<span class=\\"badge badge-light nmb-05 text-nowrap text-truncate mw-100 align-bottom\\">
Expires
<time datetime=\\"946756800000\\">
in 5 hours
</time>
<div class=\\"progress silence-progress bg-white\\">
<div class=\\"progress-bar bg-success\\"
role=\\"progressbar\\"
style=\\"width: 50%;\\"
aria-valuenow=\\"50\\"
aria-valuemin=\\"0\\"
aria-valuemax=\\"100\\"
>
</div>
</div>
</span>
</span>
</span>
</div>
</div>
"
`;
exports[`<Silence /> matches snapshot with expaned details 1`] = `
"
<div class=\\"card mt-1 border-0 p-1\\">
<div class=\\"card-text mb-0\\">
<span class=\\"text-muted my-1\\">
Fake silence
<span class=\\"blockquote-footer pt-1\\">
<a class=\\"float-right cursor-pointer\\">
<svg aria-hidden=\\"true\\"
data-prefix=\\"fas\\"
data-icon=\\"chevron-down\\"
class=\\"svg-inline--fa fa-chevron-down fa-w-14 \\"
role=\\"img\\"
xmlns=\\"http://www.w3.org/2000/svg\\"
viewbox=\\"0 0 448 512\\"
>
<path fill=\\"currentColor\\"
d=\\"M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z\\"
>
</path>
</svg>
</a>
<cite class=\\"components-grid-alertgroup-silences mr-2\\">
me@example.com
</cite>
</span>
</span>
</div>
<div class=\\"mt-1\\">
<span class=\\"components-label components-label-with-hover text-nowrap text-truncate badge badge-warning mw-100\\">
@alertmanager: default
</span>
<a class=\\"badge badge-secondary text-nowrap text-truncate px-1 mr-1\\"
href=\\"file:///mock/#/silences/4cf5fd82-1edd-4169-99d1-ff8415e72179\\"
target=\\"_blank\\"
rel=\\"noopener noreferrer\\"
>
4cf5fd82-1edd-4169-99d1-ff8415e72179
</a>
<span class=\\"badge badge-secondary text-nowrap text-truncate px-1 mr-1\\">
Silenced
<time datetime=\\"946720800000\\">
5 hours ago
</time>
</span>
<span class=\\"badge badge-secondary text-nowrap text-truncate px-1 mr-1\\">
Expires
<time datetime=\\"946756800000\\">
in 5 hours
</time>
</span>
<span class=\\"badge badge-success text-nowrap text-truncate px-1 mr-1\\">
alertname=MockAlert
</span>
</div>
</div>
"
`;
@@ -228,4 +228,4 @@ const Silence = inject("alertStore")(
)
);
export { Silence };
export { Silence, SilenceDetails, SilenceExpiryBadgeWithProgress };
@@ -0,0 +1,194 @@
import React from "react";
import { Provider } from "mobx-react";
import { mount, shallow } from "enzyme";
import toDiffableHtml from "diffable-html";
import { advanceTo, clear } from "jest-date-mock";
import { AlertStore } from "Stores/AlertStore";
import { Silence, SilenceDetails, SilenceExpiryBadgeWithProgress } from ".";
const mockAfterUpdate = jest.fn();
const alertmanager = {
name: "default",
uri: "file:///mock",
state: "suppressed",
startsAt: "2000-01-01T10:00:00Z",
endsAt: "0001-01-01T00:00:00Z",
source: "localhost/prometheus",
silencedBy: ["4cf5fd82-1edd-4169-99d1-ff8415e72179"]
};
const silence = {
id: "4cf5fd82-1edd-4169-99d1-ff8415e72179",
matchers: [
{
name: "alertname",
value: "MockAlert",
isRegex: false
}
],
startsAt: "2000-01-01T10:00:00Z",
endsAt: "2000-01-01T20:00:00Z",
createdAt: "0001-01-01T00:00:00Z",
createdBy: "me@example.com",
comment: "Fake silence",
jiraID: "",
jiraURL: ""
};
let alertStore;
beforeEach(() => {
advanceTo(new Date(2000, 0, 1, 15, 0, 0));
alertStore = new AlertStore([]);
alertStore.data.upstreams = {
counters: {
total: 1,
healthy: 1,
failed: 0
},
instances: [
{
name: "default",
uri: "file:///mock",
error: ""
}
]
};
alertStore.data.silences = {
default: {
"4cf5fd82-1edd-4169-99d1-ff8415e72179": silence
}
};
});
afterEach(() => {
// reset Date() to current time
clear();
});
const MountedSilence = () => {
return mount(
<Provider alertStore={alertStore}>
<Silence
alertStore={alertStore}
alertmanager={alertmanager}
silenceID="4cf5fd82-1edd-4169-99d1-ff8415e72179"
afterUpdate={mockAfterUpdate}
/>
</Provider>
);
};
describe("<Silence />", () => {
it("matches snapshot when data is present in alertStore", () => {
const tree = MountedSilence().find("Silence");
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
it("renders full silence when data is present in alertStore", () => {
const tree = MountedSilence().find("Silence");
const fallback = tree.find("FallbackSilenceDesciption");
expect(fallback).toHaveLength(0);
});
it("matches snapshot when data is not present in alertStore", () => {
alertStore.data.silences = {};
const tree = MountedSilence().find("Silence");
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
it("renders FallbackSilenceDesciption when Alertmanager data is not present in alertStore", () => {
alertStore.data.silences = {};
const tree = MountedSilence();
const fallback = tree.find("FallbackSilenceDesciption");
expect(fallback).toHaveLength(1);
expect(tree.text()).toBe(
"Silenced by default/4cf5fd82-1edd-4169-99d1-ff8415e72179"
);
});
it("renders FallbackSilenceDesciption when silence data is not present in alertStore", () => {
alertStore.data.silences.default = {};
const tree = MountedSilence();
const fallback = tree.find("FallbackSilenceDesciption");
expect(fallback).toHaveLength(1);
expect(tree.text()).toBe(
"Silenced by default/4cf5fd82-1edd-4169-99d1-ff8415e72179"
);
});
it("clicking on expand toggle shows silence details", () => {
const tree = MountedSilence();
const toggle = tree.find("a.float-right.cursor-pointer");
toggle.simulate("click");
const details = tree.find("SilenceDetails");
expect(details).toHaveLength(1);
});
it("matches snapshot with expaned details", () => {
const tree = MountedSilence().find("Silence");
tree.instance().collapse.toggle();
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
it("renders comment as link when jiraURL is set", () => {
alertStore.data.silences.default[silence.id].jiraURL =
"http://jira.example.com";
const tree = MountedSilence().find("Silence");
const link = tree.find("a[href='http://jira.example.com']");
expect(link).toHaveLength(1);
expect(link.text()).toBe("Fake silence");
});
});
const ShallowSilenceDetails = () => {
return shallow(
<SilenceDetails alertmanager={alertmanager} silence={silence} />
);
};
describe("<SilenceDetails />", () => {
it("unexpired silence endsAt label uses 'secondary' class", () => {
const tree = ShallowSilenceDetails();
const endsAt = tree.find("span.badge").at(1);
expect(endsAt.html()).toMatch(/badge-secondary/);
});
it("expired silence endsAt label uses 'danger' class", () => {
advanceTo(new Date(2000, 0, 1, 23, 0, 0));
const tree = ShallowSilenceDetails();
const endsAt = tree.find("span.badge").at(1);
expect(endsAt.html()).toMatch(/badge-danger/);
});
});
const ShallowSilenceExpiryBadgeWithProgress = () => {
return shallow(<SilenceExpiryBadgeWithProgress silence={silence} />);
};
describe("<SilenceExpiryBadgeWithProgress />", () => {
it("renders with class 'danger' and no progressbar when expired", () => {
advanceTo(new Date(2001, 0, 1, 23, 0, 0));
const tree = ShallowSilenceExpiryBadgeWithProgress();
expect(tree.html()).toMatch(/badge-danger/);
expect(tree.text()).toBe("Expired <t />");
});
it("progressbar uses class 'danger' when > 90%", () => {
advanceTo(new Date(2000, 0, 1, 19, 30, 0));
const tree = ShallowSilenceExpiryBadgeWithProgress();
expect(tree.html()).toMatch(/progress-bar bg-danger/);
});
it("progressbar uses class 'danger' when > 75%", () => {
advanceTo(new Date(2000, 0, 1, 17, 45, 0));
const tree = ShallowSilenceExpiryBadgeWithProgress();
expect(tree.html()).toMatch(/progress-bar bg-warning/);
});
});
+3
View File
@@ -15,6 +15,9 @@ require("jest-localstorage-mock");
// favico.js needs canvas
require("jest-canvas-mock");
// used to mock current time since we render moment.fromNow() in some places
require("jest-date-mock");
// fetch is used in multiple places to interact with Go backend
// or upstream Alertmanager API
global.fetch = require("jest-fetch-mock");