import React from "react";
const { render, fireEvent, waitFor } = require("@testing-library/react");
import { MemoryRouter } from "react-router-dom";
import { SearchWidget } from "./search";
declare var global: Window;
function renderWithRouter(component) {
return render({component});
}
it("renders without crashing", () => {
const { getByPlaceholderText } = renderWithRouter();
expect(getByPlaceholderText(/Site search/)).toBeDefined();
});
describe("Tests using XHR", () => {
beforeEach(() => {
// Mock Fetch API
jest.spyOn(global, "fetch").mockImplementation(() =>
Promise.resolve({
status: 200,
ok: true,
json: () =>
Promise.resolve({
titles: {
"/docs/Web/HTML/Element/abbr": {
title: ": The Abbreviation element",
popularity: 0.0,
},
},
}),
} as Response)
);
(global.fetch as any).mockClear();
});
test("input placeholder changes when focused", async () => {
const { getByPlaceholderText } = renderWithRouter();
const input = getByPlaceholderText(/Site search/);
fireEvent.focus(input);
expect(getByPlaceholderText(/Initializing/));
await waitFor(() => getByPlaceholderText(/Go ahead/));
});
test("XHR request on focusing input the first time", () => {
const { getByPlaceholderText } = renderWithRouter();
const input = getByPlaceholderText(/Site search/);
// Fire initial focus event
fireEvent.focus(input);
// Expect XHR
expect(global.fetch).toHaveBeenCalledTimes(1);
// Clear the mock fetch
(global.fetch as any).mockClear();
// Fire focus event again to ensure it's not called again
fireEvent.focus(input);
expect(global.fetch).toHaveBeenCalledTimes(0);
});
test("should set titles in localStorage", async () => {
const { getByPlaceholderText } = renderWithRouter();
const input = getByPlaceholderText(/Site search/);
// Focus input to get titles from XHR
fireEvent.focus(input);
expect(global.localStorage.getItem("titles")).toBeDefined();
});
test("should NOT get search results", async () => {
const { getByPlaceholderText, getByText } = renderWithRouter(
);
const input = getByPlaceholderText(/Site search/);
// Focus input to get titles from XHR
fireEvent.focus(input);
fireEvent.change(input, { target: { value: "div" } });
// Get the search results
await waitFor(() => getByText("nothing found"));
});
test("should get search results", async () => {
const { getByPlaceholderText, getByText } = renderWithRouter(
);
const input = getByPlaceholderText(/Site search/);
// Focus input to get titles from XHR
fireEvent.focus(input);
fireEvent.change(input, { target: { value: "ABb" } });
// Get the search results
// But can't use getByText on title because it's peppered with
// tags. But the small test with the path should be findable.
await waitFor(() => getByText(/Web \/ HTML \/ Element \/ abbr/));
});
test("should get search results by URI", async () => {
const { getByText, getByPlaceholderText } = renderWithRouter(
);
const input = getByPlaceholderText(/Site search/);
// Focus input to get titles from XHR
fireEvent.focus(input);
fireEvent.change(input, {
target: { value: "/dwm/mtabr" },
});
// Get the search results
await waitFor(() => getByText(/Fuzzy searching by URI/));
await waitFor(() => getByText(/The Abbreviation element/));
});
test("should redirect when clicking a search result", async () => {
const { container, getByText, getByPlaceholderText } = renderWithRouter(
);
const input = getByPlaceholderText(/Site search/);
// Focus input to get titles from XHR
fireEvent.focus(input);
fireEvent.change(input, {
target: { value: "/dwm/mtabr" },
});
// Get the search results
await waitFor(() => getByText(/The Abbreviation element/));
const targetResult = container.querySelector("div.highlit");
// Click the highlit result
fireEvent.click(targetResult);
// XXX (peterbe) This test is actually a bit broken. It doesn't
// actually ever test that the click successfully triggered a
// redirect to a new location. For some reason
// `window.location.pathname` doesn't change even though I'm
// confident it really does call `navigate($NEWURL)` in the
// main component.
// Let's leave it until we learn more about how to test
// with react-router v6.
// By the way, here's an example of how they do it within tests
// inside react-router-dom itself:
// https://github.com/ReactTraining/react-router/blob/e576ca7bf65f62680cc61b7f0ea29f0c8fd13d65/packages/react-router-dom/__tests__/navigate-encode-params-test.js#L53
// console.log(window.location.pathname);
});
});