fix(tests): move useFetchGet mocks to __fixtures__

This commit is contained in:
Łukasz Mierzwa
2020-10-27 17:46:02 +00:00
committed by Łukasz Mierzwa
parent 6b81ddaf28
commit 0408e04900
15 changed files with 253 additions and 112 deletions

View File

@@ -5,11 +5,12 @@ import { mount } from "enzyme";
import toDiffableHtml from "diffable-html";
import { MockThemeContext } from "__mocks__/Theme";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { Settings } from "Stores/Settings";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { AlertGroupSortConfiguration } from "./AlertGroupSortConfiguration";
let settingsStore: Settings;
beforeEach(() => {
settingsStore = new Settings(null);
@@ -18,7 +19,6 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
});
const FakeConfiguration = () => {
@@ -51,6 +51,16 @@ describe("<AlertGroupSortConfiguration />", () => {
});
it("changing sort order value update settingsStore", () => {
useFetchGetMock.fetch.setMockedData({
response: null,
error: "fake error",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
settingsStore.gridConfig.setSortOrder("label");
expect(settingsStore.gridConfig.config.sortOrder).toBe(
settingsStore.gridConfig.options.label.value
@@ -119,11 +129,14 @@ describe("<AlertGroupSortConfiguration />", () => {
});
it("label select handles fetch errors", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "fake error",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = ExpandSortLabelSuggestions();
const options = tree.find("div.react-select__option");

View File

@@ -7,8 +7,8 @@ import fetchMock from "fetch-mock";
import toDiffableHtml from "diffable-html";
import { MockThemeContext } from "__mocks__/Theme";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { Settings } from "Stores/Settings";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { MultiGridConfiguration } from "./MultiGridConfiguration";
let settingsStore: Settings;
@@ -25,8 +25,6 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
fetchMock.reset();
});
const FakeConfiguration = () => {
@@ -63,11 +61,14 @@ describe("<MultiGridConfiguration />", () => {
});
it("label select handles fetch errors", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "fake error",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = ExpandSortLabelSuggestions();
const options = tree.find("div.react-select__option");

View File

@@ -10,7 +10,6 @@ import { PressKey } from "__mocks__/PressKey";
import { APISilenceT } from "Models/APITypes";
import { AlertStore } from "Stores/AlertStore";
import { SilenceFormStore } from "Stores/SilenceFormStore";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { useFetchDelete } from "__mocks__/Hooks/useFetchDelete";
import { DeleteSilence, DeleteSilenceModalContent } from "./DeleteSilence";
@@ -50,7 +49,6 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
useFetchDelete.mockReset();
clear();
document.body.className = "";

View File

@@ -5,9 +5,10 @@ import { mount, render } from "enzyme";
import toDiffableHtml from "diffable-html";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { AlertStore, NewUnappliedFilter } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { useFetchGet } from "Hooks/useFetchGet";
import { FilterInput } from ".";
let alertStore: AlertStore;
@@ -29,7 +30,6 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
(useFetchGet as any).mockReset();
global.window.innerWidth = originalInnerWidth;
});
@@ -142,8 +142,8 @@ describe("<FilterInput Autosuggest />", () => {
jest.runOnlyPendingTimers();
});
expect((useFetchGet as any).fetch.calls).toHaveLength(1);
expect((useFetchGet as any).fetch.calls[0]).toContain(
expect(useFetchGetMock.fetch.calls).toHaveLength(1);
expect(useFetchGetMock.fetch.calls[0]).toContain(
"./autocomplete.json?term=cluster"
);
});
@@ -154,7 +154,7 @@ describe("<FilterInput Autosuggest />", () => {
act(() => {
jest.runOnlyPendingTimers();
});
expect((useFetchGet as any).fetch.calls).toHaveLength(0);
expect(useFetchGetMock.fetch.calls).toHaveLength(0);
});
it("clicking on a suggestion adds it to filters", async () => {
@@ -182,12 +182,14 @@ describe("<FilterInput Autosuggest />", () => {
});
it("handles failed suggestion fetches", async () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "fake error",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedInput();

View File

@@ -4,9 +4,10 @@ import { mount } from "enzyme";
import { advanceTo, clear } from "jest-date-mock";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { EmptyAPIResponse } from "__mocks__/Fetch";
import { AlertStore } from "Stores/AlertStore";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { useFetchGet } from "Hooks/useFetchGet";
import { useFetchDelete } from "__mocks__/Hooks/useFetchDelete";
import { PaginatedAlertList } from ".";
@@ -40,7 +41,6 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
useFetchDelete.mockReset();
clear();
document.body.className = "";
@@ -48,11 +48,14 @@ afterEach(() => {
describe("<PaginatedAlertList />", () => {
it("renders Placeholder while loading preview", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: false,
error: null,
isLoading: true,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = mount(
<PaginatedAlertList alertStore={alertStore} filters={["foo=bar"]} />
@@ -61,11 +64,14 @@ describe("<PaginatedAlertList />", () => {
});
it("renders Placeholder while response is empty", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: false,
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = mount(
<PaginatedAlertList alertStore={alertStore} filters={["foo=bar"]} />
@@ -82,11 +88,14 @@ describe("<PaginatedAlertList />", () => {
});
it("renders empty LabelSetList with empty response", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: EmptyAPIResponse(),
error: false,
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = mount(
<PaginatedAlertList alertStore={alertStore} filters={["foo=bar"]} />
@@ -113,11 +122,14 @@ describe("<PaginatedAlertList />", () => {
});
it("handles empty grid response correctly", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: EmptyAPIResponse(),
error: false,
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = mount(
<PaginatedAlertList alertStore={alertStore} filters={["foo=bar"]} />
@@ -126,11 +138,14 @@ describe("<PaginatedAlertList />", () => {
});
it("renders FetchError on failed preview fetch", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "fake error",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = mount(
<PaginatedAlertList alertStore={alertStore} filters={["foo=bar"]} />

View File

@@ -7,15 +7,15 @@ import toDiffableHtml from "diffable-html";
import { advanceTo, clear } from "jest-date-mock";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { MockSilence } from "__mocks__/Alerts";
import { MockThemeContext } from "__mocks__/Theme";
import { PressKey } from "__mocks__/PressKey";
import { APISilenceT } from "Models/APITypes";
import { APISilenceT, APIManagedSilenceT } from "Models/APITypes";
import { AlertStore } from "Stores/AlertStore";
import { Settings } from "Stores/Settings";
import { SilenceFormStore } from "Stores/SilenceFormStore";
import { ThemeContext } from "Components/Theme";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import Browser from ".";
let alertStore: AlertStore;
@@ -62,14 +62,13 @@ afterEach(() => {
jest.restoreAllMocks();
jest.clearAllTimers();
clear();
useFetchGet.mockReset();
localStorage.setItem("fetchConfig.interval", "");
global.window.innerWidth = 1024;
});
const MockSilenceList = (count: number) => {
const silences = [];
const MockSilenceList = (count: number): APIManagedSilenceT[] => {
const silences: APIManagedSilenceT[] = [];
for (let index = 1; index <= count; index++) {
const silence = MockSilence();
silence.id = `silence${index}`;
@@ -77,6 +76,7 @@ const MockSilenceList = (count: number) => {
cluster: cluster,
alertCount: 123,
silence: silence,
isExpired: false,
});
}
return silences;
@@ -99,7 +99,7 @@ const MountedBrowser = () => {
describe("<Browser />", () => {
it("fetches /silences.json on mount", () => {
MountedBrowser();
expect((useFetchGet as any).fetch.calls[0]).toBe(
expect(useFetchGetMock.fetch.calls[0]).toBe(
"./silences.json?sortReverse=0&showExpired=0&searchTerm="
);
});
@@ -123,12 +123,12 @@ describe("<Browser />", () => {
jest.runOnlyPendingTimers();
});
expect((useFetchGet as any).fetch.calls).toHaveLength(4);
expect(useFetchGetMock.fetch.calls).toHaveLength(4);
});
it("enabling reverse sort passes sortReverse=1 to the API", () => {
const tree = MountedBrowser();
expect((useFetchGet as any).fetch.calls[0]).toBe(
expect(useFetchGetMock.fetch.calls[0]).toBe(
"./silences.json?sortReverse=0&showExpired=0&searchTerm="
);
@@ -136,7 +136,7 @@ describe("<Browser />", () => {
expect(sortOrder.text()).toBe("Sort order");
sortOrder.simulate("click");
expect((useFetchGet as any).fetch.calls[1]).toBe(
expect(useFetchGetMock.fetch.calls[1]).toBe(
"./silences.json?sortReverse=1&showExpired=0&searchTerm="
);
});
@@ -147,7 +147,7 @@ describe("<Browser />", () => {
const expiredCheckbox = tree.find("input[type='checkbox']");
expiredCheckbox.simulate("change", { target: { checked: true } });
expect((useFetchGet as any).fetch.calls[1]).toBe(
expect(useFetchGetMock.fetch.calls[1]).toBe(
"./silences.json?sortReverse=0&showExpired=1&searchTerm="
);
});
@@ -161,21 +161,24 @@ describe("<Browser />", () => {
act(() => {
jest.advanceTimersByTime(1000);
});
expect((useFetchGet as any).fetch.calls).toHaveLength(2);
expect((useFetchGet as any).fetch.calls[0]).toBe(
expect(useFetchGetMock.fetch.calls).toHaveLength(2);
expect(useFetchGetMock.fetch.calls[0]).toBe(
"./silences.json?sortReverse=0&showExpired=0&searchTerm="
);
expect((useFetchGet as any).fetch.calls[1]).toBe(
expect(useFetchGetMock.fetch.calls[1]).toBe(
"./silences.json?sortReverse=0&showExpired=0&searchTerm=foo"
);
});
it("renders loading placeholder before fetch finishes", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: null,
isLoading: true,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
expect(tree.find("Placeholder")).toHaveLength(1);
@@ -183,11 +186,14 @@ describe("<Browser />", () => {
});
it("renders loading placeholder before fetch finishes", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: null,
isLoading: true,
isRetrying: true,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
expect(tree.find("Placeholder")).toHaveLength(1);
@@ -195,11 +201,14 @@ describe("<Browser />", () => {
});
it("renders empty placeholder after fetch with zero results", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: [],
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
expect(tree.find("Placeholder")).toHaveLength(1);
@@ -207,17 +216,21 @@ describe("<Browser />", () => {
});
it("renders silences after successful fetch", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: [
{
cluster: cluster,
alertCount: 123,
silence: silence,
isExpired: false,
},
],
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
expect(tree.find("ManagedSilence")).toHaveLength(1);
@@ -225,11 +238,14 @@ describe("<Browser />", () => {
it("renders only first 6 silences on desktop", () => {
global.window.innerWidth = 1024;
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: MockSilenceList(7),
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
expect(tree.find("ManagedSilence")).toHaveLength(6);
@@ -237,22 +253,28 @@ describe("<Browser />", () => {
it("renders only first 6 silences on mobile", () => {
global.window.innerWidth = 500;
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: MockSilenceList(7),
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
expect(tree.find("ManagedSilence")).toHaveLength(4);
});
it("renders last silence after page change", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: MockSilenceList(7),
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
@@ -268,11 +290,14 @@ describe("<Browser />", () => {
});
it("renders next/previous page after arrow key press", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: MockSilenceList(13),
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
@@ -314,11 +339,14 @@ describe("<Browser />", () => {
});
it("resets pagination to last page on truncation", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: MockSilenceList(13),
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
@@ -329,22 +357,28 @@ describe("<Browser />", () => {
expect(tree.find("ManagedSilence")).toHaveLength(1);
expect(tree.find("li.page-item").at(3).hasClass("active")).toBe(true);
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: MockSilenceList(8),
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
tree.find("button.btn-secondary").simulate("click");
expect(tree.find("ManagedSilence")).toHaveLength(2);
expect(tree.find("li.page-item").at(2).hasClass("active")).toBe(true);
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: [],
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
tree.find("button.btn-secondary").simulate("click");
@@ -353,11 +387,14 @@ describe("<Browser />", () => {
});
it("renders error after failed fetch", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "fake failure",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedBrowser();
@@ -367,7 +404,7 @@ describe("<Browser />", () => {
it("resets the timer on unmount", () => {
const tree = MountedBrowser();
expect((useFetchGet as any).fetch.calls).toHaveLength(1);
expect(useFetchGetMock.fetch.calls).toHaveLength(1);
tree.unmount();
@@ -376,6 +413,6 @@ describe("<Browser />", () => {
jest.runOnlyPendingTimers();
});
expect((useFetchGet as any).fetch.calls).toHaveLength(1);
expect(useFetchGetMock.fetch.calls).toHaveLength(1);
});
});

View File

@@ -6,7 +6,8 @@ import toDiffableHtml from "diffable-html";
import { MockThemeContext } from "__mocks__/Theme";
import { NewEmptyMatcher, MatcherWithIDT } from "Stores/SilenceFormStore";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { useFetchGet } from "Hooks/useFetchGet";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { LabelNameInput } from "./LabelNameInput";
let matcher: MatcherWithIDT;
@@ -20,7 +21,7 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
(useFetchGet as jest.MockedFunction<typeof useFetchGetMock>).mockReset();
});
const MountedLabelNameInput = (isValid: boolean) => {
@@ -70,15 +71,21 @@ describe("<LabelNameInput />", () => {
it("populates suggestions on mount", () => {
MountedLabelNameInput(true);
expect(useFetchGet.mock.calls[0][0]).toBe("./labelNames.json");
expect(
(useFetchGet as jest.MockedFunction<typeof useFetchGetMock>).mock
.calls[0][0]
).toBe("./labelNames.json");
});
it("handles fetch errors when populating suggestions", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "fake error",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedLabelNameInput(true);
tree.find("input").simulate("change", { target: { value: "f" } });

View File

@@ -4,6 +4,7 @@ import { mount } from "enzyme";
import toDiffableHtml from "diffable-html";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { MockThemeContext } from "__mocks__/Theme";
import {
SilenceFormStore,
@@ -11,7 +12,6 @@ import {
MatcherWithIDT,
} from "Stores/SilenceFormStore";
import { StringToOption } from "Common/Select";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { LabelValueInput } from "./LabelValueInput";
let silenceFormStore: SilenceFormStore;
@@ -27,7 +27,6 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
});
const MountedLabelValueInput = (isValid: boolean) => {
@@ -49,8 +48,8 @@ describe("<LabelValueInput />", () => {
it("fetches suggestions on mount", () => {
const tree = MountedLabelValueInput(true);
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
expect((useFetchGet as any).fetch.calls).toHaveLength(1);
expect((useFetchGet as any).fetch.calls[0]).toBe(
expect(useFetchGetMock.fetch.calls).toHaveLength(1);
expect(useFetchGetMock.fetch.calls[0]).toBe(
"./labelValues.json?name=cluster"
);
});
@@ -58,7 +57,7 @@ describe("<LabelValueInput />", () => {
it("doesn't fetch suggestions if name is not set", () => {
matcher.name = "";
MountedLabelValueInput(true);
expect((useFetchGet as any).fetch.calls).toHaveLength(0);
expect(useFetchGetMock.fetch.calls).toHaveLength(0);
});
it("doesn't renders ValidationError after passed validation", () => {

View File

@@ -4,12 +4,14 @@ import { mount } from "enzyme";
import toDiffableHtml from "diffable-html";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { EmptyAPIResponse } from "__mocks__/Fetch";
import {
SilenceFormStore,
NewEmptyMatcher,
MatcherWithIDT,
} from "Stores/SilenceFormStore";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { useFetchGet } from "Hooks/useFetchGet";
import { StringToOption } from "Common/Select";
import { MatchCounter } from "./MatchCounter";
@@ -25,7 +27,6 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
});
const MountedMatchCounter = () => {
@@ -41,11 +42,14 @@ describe("<MatchCounter />", () => {
});
it("renders spinner icon while fetching", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: false,
error: null,
isLoading: true,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedMatchCounter();
@@ -54,11 +58,14 @@ describe("<MatchCounter />", () => {
});
it("renders spinner icon with text-danger while retrying fetching", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: false,
error: null,
isLoading: true,
isRetrying: true,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedMatchCounter();
@@ -66,11 +73,14 @@ describe("<MatchCounter />", () => {
});
it("renders error icon on failed fetch", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "failed",
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedMatchCounter();
@@ -78,11 +88,16 @@ describe("<MatchCounter />", () => {
});
it("totalAlerts is 0 after mount", () => {
(useFetchGet as any).fetch.setMockedData({
response: { totalAlerts: 0 },
error: false,
const r = EmptyAPIResponse();
r.totalAlerts = 0;
useFetchGetMock.fetch.setMockedData({
response: r,
error: null,
isLoading: false,
isRetrying: false,
retryCount: 0,
get: jest.fn(),
cancelGet: jest.fn(),
});
const tree = MountedMatchCounter();
@@ -96,15 +111,17 @@ describe("<MatchCounter />", () => {
it("sends correct query string for a 'foo=bar' matcher", () => {
MountedMatchCounter();
expect(useFetchGet.mock.calls[0][0]).toBe("./alerts.json?q=foo%3Dbar");
expect(
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
).toBe("./alerts.json?q=foo%3Dbar");
});
it("sends correct query string for a 'foo=~bar' matcher", () => {
matcher.isRegex = true;
MountedMatchCounter();
expect(useFetchGet.mock.calls[0][0]).toBe(
"./alerts.json?q=foo%3D~%5Ebar%24"
);
expect(
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
).toBe("./alerts.json?q=foo%3D~%5Ebar%24");
});
it("sends correct query string for a 'foo=~(bar|baz)' matcher", () => {
@@ -112,9 +129,9 @@ describe("<MatchCounter />", () => {
matcher.isRegex = true;
silenceFormStore.data.setAlertmanagers([]);
MountedMatchCounter();
expect(useFetchGet.mock.calls[0][0]).toBe(
"./alerts.json?q=foo%3D~%5E%28bar%7Cbaz%29%24"
);
expect(
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
).toBe("./alerts.json?q=foo%3D~%5E%28bar%7Cbaz%29%24");
});
it("selecting one Alertmanager instance appends it to the filters", () => {
@@ -125,9 +142,9 @@ describe("<MatchCounter />", () => {
},
]);
MountedMatchCounter();
expect(useFetchGet.mock.calls[0][0]).toBe(
"./alerts.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%29%24"
);
expect(
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
).toBe("./alerts.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%29%24");
});
it("selecting two Alertmanager instances appends it correctly to the filters", () => {
@@ -142,7 +159,9 @@ describe("<MatchCounter />", () => {
},
]);
MountedMatchCounter();
expect(useFetchGet.mock.calls[0][0]).toBe(
expect(
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
).toBe(
"./alerts.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%7Cam2%29%24"
);
});

View File

@@ -8,8 +8,9 @@ import { EmptyAPIResponse } from "__mocks__/Fetch";
import { MockAlertGroup, MockAlert } from "__mocks__/Alerts";
import { AlertStore } from "Stores/AlertStore";
import { SilenceFormStore, NewEmptyMatcher } from "Stores/SilenceFormStore";
import { useFetchGet } from "Hooks/useFetchGet";
import { StringToOption } from "Common/Select";
import { useFetchGet } from "__mocks__/Hooks/useFetchGet";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { SilencePreview } from ".";
let alertStore: AlertStore;
@@ -28,7 +29,7 @@ beforeEach(() => {
afterEach(() => {
jest.restoreAllMocks();
useFetchGet.mockReset();
(useFetchGet as jest.MockedFunction<typeof useFetchGetMock>).mockReset();
});
const MockAPIResponse = () => {
@@ -103,7 +104,7 @@ describe("<SilencePreview />", () => {
});
it("matches snapshot", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: MockAPIResponse(),
error: false,
isLoading: false,
@@ -115,7 +116,7 @@ describe("<SilencePreview />", () => {
});
it("renders Placeholder while loading preview", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: false,
isLoading: true,
@@ -132,7 +133,7 @@ describe("<SilencePreview />", () => {
});
it("handles empty grid response correctly", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: EmptyAPIResponse(),
error: false,
isLoading: false,
@@ -144,7 +145,7 @@ describe("<SilencePreview />", () => {
});
it("renders FetchError on failed fetch", () => {
(useFetchGet as any).fetch.setMockedData({
useFetchGetMock.fetch.setMockedData({
response: null,
error: "Fetch error",
isLoading: false,

View File

@@ -9,6 +9,8 @@ import fetchMock from "fetch-mock";
import { FetchRetryConfig } from "Common/Fetch";
import { useFetchGet } from "./useFetchGet";
jest.unmock("./useFetchGet");
describe("useFetchGet", () => {
beforeAll(() => {
fetchMock.mock("http://localhost/ok", {

View File

@@ -22,10 +22,7 @@ interface ResponseState<T> {
retryCount: number;
}
const useFetchGet = <T>(
uri: string,
{ autorun = true, deps = [], fetcher = null }: FetchGetOptionsT = {}
): {
export interface FetchGetResultT<T> {
response: null | T;
error: null | string;
isLoading: boolean;
@@ -33,7 +30,12 @@ const useFetchGet = <T>(
retryCount: number;
get: () => void;
cancelGet: () => void;
} => {
}
const useFetchGet = <T>(
uri: string,
{ autorun = true, deps = [], fetcher = null }: FetchGetOptionsT = {}
): FetchGetResultT<T> => {
const [response, setResponse] = useState<ResponseState<T>>({
response: null,
error: null,

View File

@@ -1,16 +1,35 @@
import { useState, useEffect, useCallback } from "react";
import { MockAPIResponse, MockSilenceResponse } from "__mocks__/Fetch";
import { FetchGetResultT } from "Hooks/useFetchGet";
import { APIAlertsResponseT, APIManagedSilenceT } from "Models/APITypes";
type responseT = null | string[] | APIAlertsResponseT | APIManagedSilenceT[];
interface mockedDataT {
response: any;
error: undefined | string;
response: undefined | responseT;
error: undefined | null | string;
isLoading: undefined | boolean;
isRetrying: undefined | boolean;
retryCount: undefined | number;
get: () => void;
cancelGet: () => void;
}
const MockFetchStats = {
getCalls: [] as string[],
interface mockFetchStatsT {
getCalls: string[];
readonly calls: string[];
wasCalled: (uri: string) => void;
reset: () => void;
mockedData: mockedDataT;
setMockedData: (data: mockedDataT) => void;
}
const mockGet = jest.fn();
const mockCancelGet = jest.fn();
const MockFetchStats: mockFetchStatsT = {
getCalls: [],
get calls() {
return this.getCalls;
},
@@ -18,12 +37,15 @@ const MockFetchStats = {
this.getCalls.push(uri);
},
reset() {
this.getCalls = [] as string[];
this.getCalls = [];
this.mockedData = {
response: undefined,
error: undefined,
isLoading: undefined,
isRetrying: undefined,
retryCount: undefined,
get: mockGet,
cancelGet: mockCancelGet,
};
},
mockedData: {
@@ -31,14 +53,20 @@ const MockFetchStats = {
error: undefined,
isLoading: undefined,
isRetrying: undefined,
} as mockedDataT,
retryCount: undefined,
get: mockGet,
cancelGet: mockCancelGet,
},
setMockedData(data: mockedDataT) {
this.mockedData = data;
},
};
const Mock = (uri: string, { autorun = true, deps = [] } = {}) => {
const [response, setResponse] = useState(null as null | any);
const useFetchGetMock = (
uri: string,
{ autorun = true, deps = [] } = {}
): FetchGetResultT<responseT> => {
const [response, setResponse] = useState(null as responseT);
const [error] = useState(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isRetrying] = useState<boolean>(false);
@@ -123,17 +151,17 @@ const Mock = (uri: string, { autorun = true, deps = [] } = {}) => {
MockFetchStats.mockedData.isRetrying !== undefined
? MockFetchStats.mockedData.isRetrying
: isRetrying,
retryCount:
MockFetchStats.mockedData.retryCount !== undefined
? MockFetchStats.mockedData.retryCount
: 0,
get,
cancelGet,
};
};
const useFetchGet = jest.fn(Mock);
(useFetchGet as any).fetch = MockFetchStats;
(useFetchGet as any).mockReset = () => {
useFetchGet.mockClear();
useFetchGet.mockImplementation(Mock);
MockFetchStats.reset();
};
useFetchGetMock.fetch = MockFetchStats;
useFetchGetMock._mockGet = mockGet;
useFetchGetMock._cancelGet = mockCancelGet;
export { useFetchGet };
export { useFetchGetMock };

View File

@@ -1,4 +1,8 @@
import { APIAlertsResponseT, APILabelCounterT } from "Models/APITypes";
import {
APIAlertsResponseT,
APILabelCounterT,
APIManagedSilenceT,
} from "Models/APITypes";
import { MockAlert, MockAlertGroup, MockSilence } from "./Alerts";
const EmptyAPIResponse = (): APIAlertsResponseT => ({
@@ -109,7 +113,7 @@ const MockAPIResponse = () => {
};
const MockSilenceResponse = (cluster: string, count: number) => {
const silences = [];
const silences: APIManagedSilenceT[] = [];
for (let index = 1; index <= count; index++) {
const silence = MockSilence();
silence.id = `silence${index}`;

View File

@@ -4,6 +4,11 @@ import Adapter from "enzyme-adapter-react-16";
import { FetchRetryConfig } from "Common/Fetch";
import { useFetchGetMock } from "__fixtures__/useFetchGet";
import { useFetchGet } from "Hooks/useFetchGet";
jest.mock("Hooks/useFetchGet");
// https://github.com/airbnb/enzyme
Enzyme.configure({ adapter: new Adapter() });
@@ -32,3 +37,11 @@ FetchRetryConfig.maxTimeout = 10;
// usePopper uses useLayoutEffect but that fails in enzyme
React.useLayoutEffect = React.useEffect;
beforeEach(() => {
useFetchGetMock.fetch.reset();
(useFetchGet as jest.MockedFunction<typeof useFetchGetMock>).mockRestore();
(useFetchGet as jest.MockedFunction<
typeof useFetchGetMock
>).mockImplementation(useFetchGetMock);
});