diff --git a/ui/package-lock.json b/ui/package-lock.json
index fd37d6f98..ec0fd83a1 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -6005,6 +6005,12 @@
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
+ "is-subset": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
+ "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=",
+ "dev": true
+ },
"is-svg": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz",
@@ -6855,6 +6861,12 @@
"jsonify": "0.0.0"
}
},
+ "json-stringify-pretty-compact": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-1.2.0.tgz",
+ "integrity": "sha512-/11Pj1OyX814QMKO7K8l85SHPTr/KsFxHp8GE2zVa0BtJgGimDjXHfM3FhC7keQdWDea7+nXf+f1de7ATZcZkQ==",
+ "dev": true
+ },
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -10015,6 +10027,16 @@
"prop-types": "15.6.2"
}
},
+ "react-element-to-string": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/react-element-to-string/-/react-element-to-string-1.0.2.tgz",
+ "integrity": "sha1-AmLyzg/6i1GOo1l7w6jcJuBVGkc=",
+ "dev": true,
+ "requires": {
+ "indent-string": "2.1.0",
+ "json-stringify-pretty-compact": "1.2.0"
+ }
+ },
"react-error-overlay": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-4.0.1.tgz",
@@ -10972,6 +10994,18 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
+ "skin-deep": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/skin-deep/-/skin-deep-1.2.0.tgz",
+ "integrity": "sha512-2TFImKMDE4bS4hm8hdpjTf4+0RXAUxK0jjQRKPrf4qypAk9zDcEldIcxdQNMUdhsJhWwFrENz7jGu5Gu/IWbbQ==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "1.0.5",
+ "is-subset": "0.1.1",
+ "react-element-to-string": "1.0.2",
+ "semver": "5.5.0"
+ }
+ },
"slash": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
diff --git a/ui/package.json b/ui/package.json
index e011fe447..697012e63 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -58,6 +58,7 @@
"markdownlint-cli": "0.13.0",
"node-sass-chokidar": "1.3.3",
"onchange": "4.1.0",
- "react-test-renderer": "16.4.2"
+ "react-test-renderer": "16.4.2",
+ "skin-deep": "1.2.0"
}
}
diff --git a/ui/src/Components/NavBar/__snapshots__/index.test.js.snap b/ui/src/Components/NavBar/__snapshots__/index.test.js.snap
new file mode 100644
index 000000000..e3a309297
--- /dev/null
+++ b/ui/src/Components/NavBar/__snapshots__/index.test.js.snap
@@ -0,0 +1,5 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` matches snapshot with 0 alerts 1`] = `"0"`;
+
+exports[` matches snapshot with 5 alerts 1`] = `"5"`;
diff --git a/ui/src/Components/NavBar/index.test.js b/ui/src/Components/NavBar/index.test.js
new file mode 100644
index 000000000..db7bb9daa
--- /dev/null
+++ b/ui/src/Components/NavBar/index.test.js
@@ -0,0 +1,77 @@
+import React from "react";
+import sd from "skin-deep";
+
+import moment from "moment";
+
+import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore";
+import { Settings } from "Stores/Settings";
+import { SilenceFormStore } from "Stores/SilenceFormStore";
+import { NavBar } from ".";
+
+let alertStore;
+let settingsStore;
+let silenceFormStore;
+
+beforeEach(() => {
+ alertStore = new AlertStore([]);
+ settingsStore = new Settings();
+ silenceFormStore = new SilenceFormStore();
+ // 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();
+});
+
+const RenderNavbar = () => {
+ return sd.shallowRender(
+
+ );
+};
+
+const ValidateNavClass = (totalFilters, expectedClass) => {
+ for (let i = 0; i < totalFilters; i++) {
+ alertStore.filters.values.push(NewUnappliedFilter(`foo=${i}`));
+ }
+ const tree = RenderNavbar();
+ const nav = tree.subTree(".navbar-nav");
+ expect(nav.props.className.split(" ")).toContain(expectedClass);
+};
+
+describe("", () => {
+ it("matches snapshot with 0 alerts", () => {
+ const tree = RenderNavbar();
+ expect(tree.text()).toMatchSnapshot();
+ });
+
+ it("matches snapshot with 5 alerts", () => {
+ alertStore.info.totalAlerts = 5;
+ const tree = RenderNavbar();
+ expect(tree.text()).toMatchSnapshot();
+ });
+
+ it("navbar-brand shows 15 alerts with totalAlerts=15", () => {
+ alertStore.info.totalAlerts = 15;
+ const tree = RenderNavbar();
+ const brand = tree.subTree(".navbar-brand");
+ expect(brand.text()).toBe("15");
+ });
+
+ it("navbar-nav includes 'flex-row' class with 0 filters", () => {
+ ValidateNavClass(0, "flex-row");
+ });
+
+ it("navbar-nav includes 'flex-row' class with 1 filter", () => {
+ ValidateNavClass(1, "flex-row");
+ });
+
+ it("navbar-nav includes 'flex-column' class with 2 filters", () => {
+ ValidateNavClass(2, "flex-column");
+ });
+
+ it("navbar-nav includes 'flex-column' class with 3 filters", () => {
+ ValidateNavClass(3, "flex-column");
+ });
+});