mirror of
https://github.com/prymitive/karma
synced 2026-09-04 11:27:19 +00:00
Merge pull request #62 from prymitive/tests-1
More test coverage for UI
This commit is contained in:
@@ -133,8 +133,7 @@ test-js-watch: .build/deps-build-node.ok
|
||||
@# https://github.com/facebook/jest/issues/3436
|
||||
@# use onchange for now
|
||||
cd ui && ./node_modules/onchange/cli.js 'src/*.js' 'src/**/*.js' -- \
|
||||
npm test -- \
|
||||
--coverage --coverageReporters=lcov --onlyChanged
|
||||
npm test -- --coverage --coverageReporters=lcov
|
||||
|
||||
.PHONY: test
|
||||
test: lint test-go test-js
|
||||
|
||||
Generated
+29
@@ -133,6 +133,12 @@
|
||||
"prop-types": "15.6.2"
|
||||
}
|
||||
},
|
||||
"@types/jest": {
|
||||
"version": "23.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.1.tgz",
|
||||
"integrity": "sha512-/UMY+2GkOZ27Vrc51pqC5J8SPd39FKt7kkoGAtWJ8s4msj0b15KehDWIiJpWY3/7tLxBQLLzJhIBhnEsXdzpgw==",
|
||||
"dev": true
|
||||
},
|
||||
"abab": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
|
||||
@@ -6257,6 +6263,17 @@
|
||||
"jest-util": "20.0.3"
|
||||
}
|
||||
},
|
||||
"jest-fetch-mock": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-1.6.5.tgz",
|
||||
"integrity": "sha512-qPz5Zf8+W16pu6cvdwXkb2SwRfxGoQbbGB6HcIBFND0gnWKMfQilZew3PSODnOWQZF/pzBPi7ZIT6Yz5D0va1Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/jest": "23.3.1",
|
||||
"isomorphic-fetch": "2.2.1",
|
||||
"promise-polyfill": "7.1.2"
|
||||
}
|
||||
},
|
||||
"jest-haste-map": {
|
||||
"version": "20.0.5",
|
||||
"resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-20.0.5.tgz",
|
||||
@@ -6465,6 +6482,12 @@
|
||||
"resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-20.0.3.tgz",
|
||||
"integrity": "sha1-i8Bw6QQUqhVcEajWTIaaDVxx2lk="
|
||||
},
|
||||
"jest-mock-console": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-mock-console/-/jest-mock-console-0.4.0.tgz",
|
||||
"integrity": "sha512-WElCbNvfqQlD7cpfHfTn1ytZ+RjKg1Ftrvr5wEjdWP7a9esXmaiZuEAPeYUSK5fd0Cra+dR1oF8HAjjKKxDQdg==",
|
||||
"dev": true
|
||||
},
|
||||
"jest-regex-util": {
|
||||
"version": "20.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-20.0.3.tgz",
|
||||
@@ -9611,6 +9634,12 @@
|
||||
"asap": "2.0.6"
|
||||
}
|
||||
},
|
||||
"promise-polyfill": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-7.1.2.tgz",
|
||||
"integrity": "sha512-FuEc12/eKqqoRYIGBrUptCBRhobL19PS2U31vMNTfyck1FxPyMfgsXyW4Mav85y/ZN1hop3hOwRlUDok23oYfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||
|
||||
@@ -52,7 +52,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-plugin-react": "7.11.1",
|
||||
"jest-fetch-mock": "1.6.5",
|
||||
"jest-localstorage-mock": "2.2.0",
|
||||
"jest-mock-console": "0.4.0",
|
||||
"markdownlint-cli": "0.13.0",
|
||||
"node-sass-chokidar": "1.3.3",
|
||||
"onchange": "4.1.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import renderer from "react-test-renderer";
|
||||
|
||||
import { FetchMock, EmptyAPIResponse } from "__mocks__/Fetch";
|
||||
import { EmptyAPIResponse } from "__mocks__/Fetch";
|
||||
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { Settings } from "Stores/Settings";
|
||||
@@ -16,8 +16,7 @@ let alertStore;
|
||||
let settingsStore;
|
||||
|
||||
beforeEach(() => {
|
||||
const response = EmptyAPIResponse();
|
||||
global.fetch = FetchMock(response);
|
||||
fetch.mockResponse(JSON.stringify(EmptyAPIResponse()));
|
||||
|
||||
alertStore = new AlertStore(["label=value"]);
|
||||
settingsStore = new Settings();
|
||||
|
||||
@@ -43,18 +43,18 @@ class BaseLabel extends Component {
|
||||
alertStore.data.colors[name][value] !== undefined
|
||||
) {
|
||||
const c = alertStore.data.colors[name][value];
|
||||
style["backgroundColor"] = `rgba(
|
||||
${c.background.red},
|
||||
${c.background.green},
|
||||
${c.background.blue},
|
||||
${c.background.alpha}
|
||||
)`;
|
||||
style["color"] = `rgba(
|
||||
${c.font.red},
|
||||
${c.font.green},
|
||||
${c.font.blue},
|
||||
${c.font.alpha}
|
||||
)`;
|
||||
style["backgroundColor"] = `rgba(${[
|
||||
c.background.red,
|
||||
c.background.green,
|
||||
c.background.blue,
|
||||
c.background.alpha
|
||||
].join(", ")})`;
|
||||
style["color"] = `rgba(${[
|
||||
c.font.red,
|
||||
c.font.green,
|
||||
c.font.blue,
|
||||
c.font.alpha
|
||||
].join(", ")})`;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import React from "react";
|
||||
import renderer from "react-test-renderer";
|
||||
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
|
||||
import { BaseLabel } from ".";
|
||||
|
||||
let alertStore;
|
||||
|
||||
beforeEach(() => {
|
||||
alertStore = new AlertStore([]);
|
||||
});
|
||||
|
||||
const FakeBaseLabel = () => {
|
||||
// BaseLabel doesn't implement render since it's an abstract component
|
||||
// Add a dummy implementation for testing
|
||||
class RenderableBaseLabel extends BaseLabel {
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return renderer.create(
|
||||
<RenderableBaseLabel alertStore={alertStore} name="foo" value="bar" />
|
||||
);
|
||||
};
|
||||
|
||||
describe("<BaseLabel />", () => {
|
||||
it("isStaticColorLabel() returns true for labels present in staticColorLabels", () => {
|
||||
alertStore.settings.values.staticColorLabels = ["foo", "job", "bar"];
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.isStaticColorLabel("job")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("isStaticColorLabel() returns false for labels not present in staticColorLabels", () => {
|
||||
alertStore.settings.values.staticColorLabels = ["foo"];
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.isStaticColorLabel("job")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("getColorClass() on a label included in staticColorLabels should return 'info'", () => {
|
||||
alertStore.settings.values.staticColorLabels = ["job"];
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.getColorClass("job", "foo")).toBe("info");
|
||||
});
|
||||
|
||||
it("getColorClass() on a label without any special color should return 'warning'", () => {
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.getColorClass("foo", "bar")).toBe("warning");
|
||||
});
|
||||
|
||||
it("getColorClass() on 'alertname' label should return 'dark'", () => {
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.getColorClass("alertname", "foo")).toBe("dark");
|
||||
});
|
||||
|
||||
it("getColorStyle() on a label included in staticColorLabels should be empty", () => {
|
||||
alertStore.settings.values.staticColorLabels = ["job"];
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.getColorStyle("job", "bar")).toMatchObject({});
|
||||
});
|
||||
|
||||
it("getColorStyle() on a label without any color information should be empty", () => {
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.getColorStyle("foo", "bar")).toMatchObject({});
|
||||
});
|
||||
|
||||
it("getColorStyle() on a label with color information should be correctly formatted", () => {
|
||||
alertStore.data.colors["foo"] = {
|
||||
bar: {
|
||||
font: { red: 1, green: 2, blue: 3, alpha: 100 },
|
||||
background: { red: 4, green: 5, blue: 6, alpha: 200 }
|
||||
}
|
||||
};
|
||||
const instance = FakeBaseLabel().getInstance();
|
||||
expect(instance.getColorStyle("foo", "bar")).toMatchObject({
|
||||
color: "rgba(1, 2, 3, 100)",
|
||||
backgroundColor: "rgba(4, 5, 6, 200)"
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,184 @@
|
||||
import React from "react";
|
||||
import renderer from "react-test-renderer";
|
||||
|
||||
import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore";
|
||||
|
||||
import { FilterInputLabel } from ".";
|
||||
|
||||
let alertStore;
|
||||
|
||||
beforeEach(() => {
|
||||
alertStore = new AlertStore([]);
|
||||
});
|
||||
|
||||
const NonEqualMatchers = ["!=", "=~", "!~", ">", "<"];
|
||||
|
||||
const MockColors = () => {
|
||||
alertStore.data.colors["foo"] = {
|
||||
bar: {
|
||||
font: { red: 1, green: 2, blue: 3, alpha: 100 },
|
||||
background: { red: 4, green: 5, blue: 6, alpha: 200 }
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const FakeLabel = (matcher, applied) => {
|
||||
const name = "foo";
|
||||
const value = "bar";
|
||||
const filter = NewUnappliedFilter(`${name}${matcher}${value}`);
|
||||
filter.applied = applied;
|
||||
filter.name = name;
|
||||
filter.matcher = matcher;
|
||||
filter.value = value;
|
||||
return renderer.create(
|
||||
<FilterInputLabel alertStore={alertStore} filter={filter} />
|
||||
);
|
||||
};
|
||||
|
||||
const ValidateClass = (matcher, applied, expectedClass) => {
|
||||
const tree = FakeLabel(matcher, applied).toJSON();
|
||||
expect(tree.props.className.split(" ")).toContain(expectedClass);
|
||||
};
|
||||
|
||||
const ValidateOnChange = newRaw => {
|
||||
const component = renderer.create(
|
||||
<FilterInputLabel
|
||||
alertStore={alertStore}
|
||||
filter={alertStore.filters.values[0]}
|
||||
/>
|
||||
);
|
||||
const tree = component.toTree();
|
||||
|
||||
// call onChange with new raw value
|
||||
tree.instance.onChange({ raw: newRaw });
|
||||
|
||||
return tree;
|
||||
};
|
||||
|
||||
describe("<FilterInputLabel /> className", () => {
|
||||
it("unapplied filter with '=' matcher should use 'badge-secondary' class", () => {
|
||||
ValidateClass("=", false, "badge-secondary");
|
||||
});
|
||||
|
||||
it("unapplied filter with any matcher other than '=' should use 'badge-secondary' class", () => {
|
||||
for (const matcher of NonEqualMatchers) {
|
||||
ValidateClass(matcher, false, "badge-secondary");
|
||||
}
|
||||
});
|
||||
|
||||
it("applied filter with '=' matcher and no color should use 'badge-warning' class", () => {
|
||||
ValidateClass("=", true, "badge-warning");
|
||||
});
|
||||
|
||||
it("applied filter with any matcher other than '=' and no color should use 'badge-warning' class", () => {
|
||||
for (const matcher of NonEqualMatchers) {
|
||||
ValidateClass(matcher, true, "badge-warning");
|
||||
}
|
||||
});
|
||||
|
||||
it("applied filter included in staticColorLabels with '=' matcher should use 'badge-info' class", () => {
|
||||
alertStore.settings.values.staticColorLabels = ["foo"];
|
||||
ValidateClass("=", true, "badge-info");
|
||||
});
|
||||
|
||||
it("applied filter included in staticColorLabels with any matcher other than '=' should use 'badge-warning' class", () => {
|
||||
alertStore.settings.values.staticColorLabels = ["foo"];
|
||||
for (const matcher of NonEqualMatchers) {
|
||||
ValidateClass(matcher, true, "badge-warning");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("<FilterInputLabel /> style", () => {
|
||||
it("unapplied filter with color information and '=' matcher should have empty style", () => {
|
||||
MockColors();
|
||||
const tree = FakeLabel("=", false).toJSON();
|
||||
expect(tree.props.style).toMatchObject({});
|
||||
});
|
||||
|
||||
it("unapplied filter with no color information and '=' matcher should have empty style", () => {
|
||||
const tree = FakeLabel("=", false).toJSON();
|
||||
expect(tree.props.style).toMatchObject({});
|
||||
});
|
||||
|
||||
it("unapplied filter with no color information and any matcher other than '=' should have empty style", () => {
|
||||
for (const matcher of NonEqualMatchers) {
|
||||
const tree = FakeLabel(matcher, false).toJSON();
|
||||
expect(tree.props.style).toMatchObject({});
|
||||
}
|
||||
});
|
||||
|
||||
it("applied filter with color information and '=' matcher should have non empty style", () => {
|
||||
MockColors();
|
||||
const tree = FakeLabel("=", true).toJSON();
|
||||
expect(tree.props.style).toMatchObject({
|
||||
color: "rgba(1, 2, 3, 100)",
|
||||
backgroundColor: "rgba(4, 5, 6, 200)"
|
||||
});
|
||||
});
|
||||
|
||||
it("applied filter with no color information and '=' matcher should have empty style", () => {
|
||||
const tree = FakeLabel("=", true).toJSON();
|
||||
expect(tree.props.style).toMatchObject({});
|
||||
});
|
||||
|
||||
it("applied filter with no color information and any matcher other than '=' should have empty style", () => {
|
||||
for (const matcher of NonEqualMatchers) {
|
||||
const tree = FakeLabel(matcher, true).toJSON();
|
||||
expect(tree.props.style).toMatchObject({});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("<FilterInputLabel /> onChange", () => {
|
||||
it("filter raw value is updated after onChange call", () => {
|
||||
alertStore.filters.values = [NewUnappliedFilter("foo=bar")];
|
||||
ValidateOnChange("baz=abc");
|
||||
expect(alertStore.filters.values).toHaveLength(1);
|
||||
expect(alertStore.filters.values).toContainEqual(
|
||||
NewUnappliedFilter("baz=abc")
|
||||
);
|
||||
});
|
||||
|
||||
it("filter is removed after onChange call with empty value", () => {
|
||||
alertStore.filters.values = [NewUnappliedFilter("foo=bar")];
|
||||
ValidateOnChange("");
|
||||
expect(alertStore.filters.values).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("onChange doesn't allow duplicates", () => {
|
||||
alertStore.filters.values = [
|
||||
NewUnappliedFilter("foo=bar"),
|
||||
NewUnappliedFilter("bar=baz")
|
||||
];
|
||||
ValidateOnChange("bar=baz");
|
||||
expect(alertStore.filters.values).toHaveLength(1);
|
||||
expect(alertStore.filters.values).not.toContainEqual(
|
||||
NewUnappliedFilter("foo=bar")
|
||||
);
|
||||
expect(alertStore.filters.values).toContainEqual(
|
||||
NewUnappliedFilter("bar=baz")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("<FilterInputLabel /> onChange", () => {
|
||||
it("clicking on the X button removes filters from alertStore", () => {
|
||||
alertStore.filters.values = [
|
||||
NewUnappliedFilter("foo=bar"),
|
||||
NewUnappliedFilter("bar=baz")
|
||||
];
|
||||
const component = renderer.create(
|
||||
<FilterInputLabel
|
||||
alertStore={alertStore}
|
||||
filter={alertStore.filters.values[0]}
|
||||
/>
|
||||
);
|
||||
const button = component.root.findByType("button");
|
||||
button.props.onClick();
|
||||
expect(alertStore.filters.values).toHaveLength(1);
|
||||
expect(alertStore.filters.values).toContainEqual(
|
||||
NewUnappliedFilter("bar=baz")
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import renderer from "react-test-renderer";
|
||||
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore";
|
||||
|
||||
import { FilteringCounterBadge } from ".";
|
||||
|
||||
@@ -54,15 +54,9 @@ const validateOnClick = value => {
|
||||
tree.props.onClick({ preventDefault: () => {} });
|
||||
|
||||
expect(alertStore.filters.values).toHaveLength(1);
|
||||
expect(alertStore.filters.values).toContainEqual({
|
||||
applied: false,
|
||||
isValid: true,
|
||||
raw: `@state=${value}`,
|
||||
hits: 0,
|
||||
name: "",
|
||||
matcher: "",
|
||||
value: ""
|
||||
});
|
||||
expect(alertStore.filters.values).toContainEqual(
|
||||
NewUnappliedFilter(`@state=${value}`)
|
||||
);
|
||||
};
|
||||
|
||||
describe("<FilteringCounterBadge />", () => {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import React from "react";
|
||||
import renderer from "react-test-renderer";
|
||||
|
||||
import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore";
|
||||
|
||||
import { FilteringLabel } from ".";
|
||||
|
||||
let alertStore;
|
||||
|
||||
beforeEach(() => {
|
||||
alertStore = new AlertStore([]);
|
||||
});
|
||||
|
||||
const RenderAndClick = (name, value) => {
|
||||
const tree = renderer
|
||||
.create(
|
||||
<FilteringLabel alertStore={alertStore} name={name} value={value} />
|
||||
)
|
||||
.toJSON();
|
||||
|
||||
tree.props.onClick({ preventDefault: () => {} });
|
||||
};
|
||||
|
||||
describe("<FilteringLabel />", () => {
|
||||
it("renders without crashing", () => {
|
||||
renderer.create(
|
||||
<FilteringLabel alertStore={alertStore} name="foo" value="bar" />
|
||||
);
|
||||
});
|
||||
|
||||
it("calling onClick() adds a new filter 'foo=bar'", () => {
|
||||
RenderAndClick("foo", "bar");
|
||||
expect(alertStore.filters.values).toHaveLength(1);
|
||||
expect(alertStore.filters.values).toContainEqual(
|
||||
NewUnappliedFilter("foo=bar")
|
||||
);
|
||||
});
|
||||
|
||||
it("calling onClick() multiple times appends extra filter 'baz=bar'", () => {
|
||||
RenderAndClick("foo", "bar");
|
||||
RenderAndClick("bar", "baz");
|
||||
expect(alertStore.filters.values).toHaveLength(2);
|
||||
expect(alertStore.filters.values).toContainEqual(
|
||||
NewUnappliedFilter("foo=bar")
|
||||
);
|
||||
expect(alertStore.filters.values).toContainEqual(
|
||||
NewUnappliedFilter("bar=baz")
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -71,7 +71,7 @@ const AlertStoreStatuses = Object.freeze({
|
||||
Failure: Symbol("failure")
|
||||
});
|
||||
|
||||
function newUnappliedFilter(raw) {
|
||||
function NewUnappliedFilter(raw) {
|
||||
return {
|
||||
applied: false,
|
||||
isValid: true,
|
||||
@@ -89,7 +89,7 @@ class AlertStore {
|
||||
values: [],
|
||||
addFilter(raw) {
|
||||
if (this.values.filter(f => f.raw === raw).length === 0) {
|
||||
this.values.push(newUnappliedFilter(raw));
|
||||
this.values.push(NewUnappliedFilter(raw));
|
||||
UpdateLocationSearch({ q: this.values.map(f => f.raw) });
|
||||
}
|
||||
},
|
||||
@@ -108,13 +108,13 @@ class AlertStore {
|
||||
this.removeFilter(oldRaw);
|
||||
} else {
|
||||
// no dups, continue with a swap
|
||||
this.values[index] = newUnappliedFilter(newRaw);
|
||||
this.values[index] = NewUnappliedFilter(newRaw);
|
||||
UpdateLocationSearch({ q: this.values.map(f => f.raw) });
|
||||
}
|
||||
}
|
||||
},
|
||||
setFilters(raws) {
|
||||
this.values = raws.map(raw => newUnappliedFilter(raw));
|
||||
this.values = raws.map(raw => NewUnappliedFilter(raw));
|
||||
UpdateLocationSearch({ q: this.values.map(f => f.raw) });
|
||||
}
|
||||
},
|
||||
@@ -318,5 +318,6 @@ export {
|
||||
AlertStoreStatuses,
|
||||
FormatUnseeBackendURI,
|
||||
FormatAPIFilterQuery,
|
||||
DecodeLocationSearch
|
||||
DecodeLocationSearch,
|
||||
NewUnappliedFilter
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ConsoleMock } from "__mocks__/Console";
|
||||
import { FetchMock, EmptyAPIResponse } from "__mocks__/Fetch";
|
||||
import { EmptyAPIResponse } from "__mocks__/Fetch";
|
||||
|
||||
import {
|
||||
AlertStore,
|
||||
@@ -9,12 +8,11 @@ import {
|
||||
} from "Stores/AlertStore";
|
||||
|
||||
beforeEach(() => {
|
||||
// wipe REACT_APP_BACKEND_URI env on each run as it's used by some tests
|
||||
delete process.env.REACT_APP_BACKEND_URI;
|
||||
fetch.resetMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// same after each
|
||||
// wipe REACT_APP_BACKEND_URI env on each run as it's used by some tests
|
||||
delete process.env.REACT_APP_BACKEND_URI;
|
||||
});
|
||||
|
||||
@@ -193,7 +191,7 @@ describe("DecodeLocationSearch", () => {
|
||||
|
||||
describe("AlertStore.fetch", () => {
|
||||
it("parseAPIResponse() rejects a response with mismatched filters", () => {
|
||||
const consoleSpy = ConsoleMock("info");
|
||||
const consoleSpy = jest.spyOn(console, "info");
|
||||
|
||||
const response = EmptyAPIResponse();
|
||||
const store = new AlertStore([]);
|
||||
@@ -203,7 +201,7 @@ describe("AlertStore.fetch", () => {
|
||||
// there should be no filters set on AlertStore instance since we started
|
||||
// with 0 and rejected response with 1 filter
|
||||
expect(store.filters.values).toHaveLength(0);
|
||||
// console.info should have been called since we emited a warning
|
||||
// console.info should have been called since we emited a log line
|
||||
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
@@ -221,7 +219,7 @@ describe("AlertStore.fetch", () => {
|
||||
|
||||
it("fetch() works with valid response", async () => {
|
||||
const response = EmptyAPIResponse();
|
||||
global.fetch = FetchMock(response);
|
||||
fetch.mockResponse(JSON.stringify(response));
|
||||
|
||||
const store = new AlertStore(["label=value"]);
|
||||
await expect(store.fetch()).resolves.toBeUndefined();
|
||||
@@ -229,18 +227,10 @@ describe("AlertStore.fetch", () => {
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1);
|
||||
expect(store.status.value).toEqual(AlertStoreStatuses.Idle);
|
||||
expect(store.info.version).toBe("fakeVersion");
|
||||
|
||||
global.fetch.mockRestore();
|
||||
});
|
||||
|
||||
it("fetch() handles response with error correctly", async () => {
|
||||
global.fetch = jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
json: () => ({
|
||||
error: "Fetch error"
|
||||
})
|
||||
})
|
||||
);
|
||||
fetch.mockResponse(JSON.stringify({ error: "Fetch error" }));
|
||||
|
||||
const store = new AlertStore([]);
|
||||
await expect(store.fetch()).resolves.toBeUndefined();
|
||||
@@ -248,19 +238,11 @@ describe("AlertStore.fetch", () => {
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1);
|
||||
expect(store.status.value).toEqual(AlertStoreStatuses.Failure);
|
||||
expect(store.info.version).toBe("unknown");
|
||||
|
||||
global.fetch.mockRestore();
|
||||
});
|
||||
|
||||
it("fetch() handles response that throws an error correctly", async () => {
|
||||
const consoleSpy = ConsoleMock("trace");
|
||||
global.fetch = jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
json: () => {
|
||||
throw new Error("Failed fetch");
|
||||
}
|
||||
})
|
||||
);
|
||||
const consoleSpy = jest.spyOn(console, "trace");
|
||||
fetch.mockReject("Fetch error");
|
||||
|
||||
const store = new AlertStore([]);
|
||||
await expect(store.fetch()).resolves.toHaveProperty("error");
|
||||
@@ -272,6 +254,5 @@ describe("AlertStore.fetch", () => {
|
||||
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
consoleSpy.mockRestore();
|
||||
global.fetch.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
const ConsoleMock = level =>
|
||||
jest.spyOn(console, level).mockImplementation(() => jest.fn());
|
||||
|
||||
export { ConsoleMock };
|
||||
@@ -1,12 +1,5 @@
|
||||
import moment from "moment";
|
||||
|
||||
const FetchMock = data =>
|
||||
jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
json: () => data
|
||||
})
|
||||
);
|
||||
|
||||
const EmptyAPIResponse = () => ({
|
||||
status: "success",
|
||||
timestamp: moment().toISOString(),
|
||||
@@ -38,4 +31,4 @@ const EmptyAPIResponse = () => ({
|
||||
}
|
||||
});
|
||||
|
||||
export { FetchMock, EmptyAPIResponse };
|
||||
export { EmptyAPIResponse };
|
||||
|
||||
@@ -1 +1,11 @@
|
||||
import mockConsole from "jest-mock-console";
|
||||
|
||||
// mock console
|
||||
mockConsole(["error", "warn", "info", "log", "trace"]);
|
||||
|
||||
// localStorage is used for Settings store
|
||||
require("jest-localstorage-mock");
|
||||
|
||||
// fetch is used in multiple places to interact with Go backend
|
||||
// or upstream Alertmanager API
|
||||
global.fetch = require("jest-fetch-mock");
|
||||
|
||||
Reference in New Issue
Block a user