react-native-use-modal-hooks
Version:
React hooks for displaying a modal window in React Native
176 lines (175 loc) • 8.48 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const React = __importStar(require("react"));
const react_1 = require("react");
const react_2 = require("@testing-library/react");
const ModalProvider_1 = require("../ModalProvider");
const useModal_1 = require("../useModal");
// Helper to render components in modal context
const renderWithProvider = (ui, options) => {
const result = react_2.render(React.createElement(ModalProvider_1.ModalProvider, null, ui), options);
return Object.assign(Object.assign({}, result), {
// Override rerender to only update children of the provider
rerender: (ui) => renderWithProvider(ui, { container: result.container }) });
};
describe("simple usage", () => {
const App = () => {
const [showModal, hideModal] = useModal_1.useModal(() => (React.createElement("div", null,
React.createElement("p", null, "Modal content"),
React.createElement("button", { onClick: hideModal }, "Hide modal"))));
return React.createElement("button", { onClick: showModal }, "Show modal");
};
it("should show the modal", () => {
const { getByText, queryByText } = renderWithProvider(React.createElement(App, null));
react_2.fireEvent.click(getByText("Show modal"));
expect(queryByText("Modal content")).toBeTruthy();
});
it("should hide the modal", () => {
const { getByText, queryByText } = renderWithProvider(React.createElement(App, null));
react_2.fireEvent.click(getByText("Show modal"));
react_2.fireEvent.click(getByText("Hide modal"));
expect(queryByText("Modal content")).not.toBeTruthy();
});
it("should hide the modal when parent component unmounts", () => {
const { getByText, queryByText, rerender } = renderWithProvider(React.createElement("div", null,
React.createElement(App, null)));
react_2.fireEvent.click(getByText("Show modal"));
rerender(React.createElement("div", null));
expect(queryByText("Modal content")).not.toBeTruthy();
});
});
describe("updating modal", () => {
it("should work with internal state", () => {
const App = () => {
const [showModal] = useModal_1.useModal(() => {
const [count, setCount] = react_1.useState(0);
return (React.createElement("div", null,
React.createElement("span", null,
"The count is ",
count),
React.createElement("button", { onClick: () => setCount(count + 1) }, "Increment")));
});
return React.createElement("button", { onClick: showModal }, "Show modal");
};
const { getByText, queryByText } = renderWithProvider(React.createElement(App, null));
react_2.fireEvent.click(getByText("Show modal"));
expect(queryByText("The count is 0")).toBeTruthy();
react_2.fireEvent.click(getByText("Increment"));
expect(queryByText("The count is 1")).toBeTruthy();
});
it("should work with external state", () => {
const App = () => {
const [count, setCount] = react_1.useState(0);
const [showModal] = useModal_1.useModal(() => (React.createElement("div", null,
React.createElement("span", null,
"The count is ",
count),
React.createElement("button", { onClick: () => setCount(count + 1) }, "Increment"))), [count]);
return React.createElement("button", { onClick: showModal }, "Show modal");
};
const { getByText, queryByText } = renderWithProvider(React.createElement(App, null));
react_2.fireEvent.click(getByText("Show modal"));
expect(queryByText("The count is 0")).toBeTruthy();
react_2.fireEvent.click(getByText("Increment"));
expect(queryByText("The count is 1")).toBeTruthy();
});
it("should not rerender when external state changes", () => {
const mountCounter = jest.fn();
class MountSpy extends React.Component {
componentDidMount() {
mountCounter();
}
render() {
return null;
}
}
const App = () => {
const [count, setCount] = react_1.useState(0);
const [showModal] = useModal_1.useModal(() => (React.createElement("div", null,
React.createElement(MountSpy, null),
React.createElement("span", null,
"The count is ",
count),
React.createElement("button", { onClick: () => setCount(count + 1) }, "Increment"))), [count]);
return React.createElement("button", { onClick: showModal }, "Show modal");
};
const { getByText } = renderWithProvider(React.createElement(App, null));
react_2.fireEvent.click(getByText("Show modal"));
react_2.fireEvent.click(getByText("Increment"));
expect(mountCounter).toHaveBeenCalledTimes(1);
});
});
describe("multiple modals", () => {
it("should show multiple modals at the same time", () => {
const App = () => {
const [showFirstModal] = useModal_1.useModal(() => React.createElement("div", null, "First modal content"));
const [showSecondModal] = useModal_1.useModal(() => React.createElement("div", null, "Second modal content"));
return (React.createElement("div", null,
React.createElement("button", { onClick: showFirstModal }, "Show first modal"),
React.createElement("button", { onClick: showSecondModal }, "Show second modal")));
};
const { getByText, queryByText } = renderWithProvider(React.createElement(App, null));
react_2.fireEvent.click(getByText("Show first modal"));
react_2.fireEvent.click(getByText("Show second modal"));
expect(queryByText("First modal content")).toBeTruthy();
expect(queryByText("Second modal content")).toBeTruthy();
});
});
describe("calling useModal without ModalProvider", () => {
const App = () => {
useModal_1.useModal(() => React.createElement("div", null, "Modal content"));
return null;
};
it("should throw an error", () => {
const consoleError = jest.fn();
jest.spyOn(console, 'error').mockImplementation(consoleError);
expect(() => react_2.render(React.createElement(App, null))).toThrow(new Error("Attempted to call useModal outside of modal context. Make sure your app is rendered inside ModalProvider."));
expect(consoleError).toHaveBeenCalled();
});
});
describe("calling useModal with class component", () => {
class Modal extends React.Component {
render() {
return React.createElement("div", null, "Modal content");
}
}
const App = () => {
useModal_1.useModal(Modal);
return null;
};
beforeEach(() => {
jest.spyOn(console, "error");
global.console.error.mockImplementation(() => { });
});
afterEach(() => {
global.console.error.mockRestore();
});
it("should throw an error", () => {
const catchError = jest.fn((e) => e.preventDefault());
window.addEventListener("error", catchError);
expect(() => {
renderWithProvider(React.createElement(App, null));
}).toThrowError(expect.objectContaining({
message: expect.stringMatching(/Only stateless components can be used as an argument to useModal/)
}));
});
});