Create with query wrapper

This commit is contained in:
Kat Huang 2024-01-08 15:57:12 -07:00
parent 78d99da6df
commit 78d40f1abc
2 changed files with 107 additions and 0 deletions

View File

@ -0,0 +1,42 @@
import React from "react";
import { useQuery, DocumentNode, OperationVariables } from "@apollo/client";
import { Text } from "react-native";
/**
* A higher-order component that provides loading and error handling for GraphQL queries.
* @param {React.ComponentType} WrappedComponent - The component to wrap.
* @param {DocumentNode} query - The GraphQL query to execute.
* @param {string} dataKey - The key in the data object to pass to the wrapped component.
* @param {Object} queryOptions - Optional. Additional options for the Apollo query.
* @returns {React.ComponentType} A component that renders the WrappedComponent with loading and error handling.
*/
/* eslint-disable react/display-name */
type WithQueryHandlingProps = {
WrappedComponent: React.ComponentType<any>;
query: DocumentNode;
dataKey: string;
queryOptions?: OperationVariables;
};
function withQueryHandling({
WrappedComponent,
query,
dataKey,
queryOptions = {},
}: WithQueryHandlingProps) {
return function (props: any) {
// You can replace 'any' with specific props type if known
const { loading, error, data } = useQuery(query, queryOptions);
if (loading) {
return <Text>Loading...</Text>;
}
if (error) {
return <Text>Error: {error.message}</Text>;
}
const specificData = data[dataKey];
return <WrappedComponent {...props} data={specificData} />;
};
}
export default withQueryHandling;

View File

@ -0,0 +1,65 @@
import React from "react";
import { render, cleanup, waitFor } from "@testing-library/react-native";
import "@testing-library/jest-native/extend-expect";
import { gql, useQuery } from "@apollo/client";
import withQueryHandling from "../../component/with-query-handling";
import { Text } from "react-native";
jest.mock("@apollo/client", () => ({
...jest.requireActual("@apollo/client"),
useQuery: jest.fn(),
}));
const MockComponent: React.FC<{ data?: string }> = ({ data }) => (
<Text>{data ? data : "No Data"}</Text>
);
const MOCK_QUERY = gql`
query GetMockData {
mockData {
id
name
description
}
}
`;
describe("withQueryHandling HOC Tests", () => {
afterEach(() => {
jest.clearAllMocks();
cleanup();
});
it("should render loading state initially", async () => {
(useQuery as jest.Mock).mockReturnValue({
loading: true,
error: undefined,
data: undefined,
});
const WrappedComponent = withQueryHandling({
WrappedComponent: MockComponent,
query: MOCK_QUERY,
dataKey: "mockDataKey",
});
const { getByText } = render(<WrappedComponent />);
await waitFor(() => {
expect(getByText("Loading...")).toBeTruthy();
});
});
it("should render the wrapped component with data", () => {
const mockData = { getShots: "shots" };
(useQuery as jest.Mock).mockReturnValue({
loading: false,
error: undefined,
data: mockData,
});
const WrappedComponent = withQueryHandling({
WrappedComponent: MockComponent,
query: MOCK_QUERY,
dataKey: "getShots",
});
const { getByText } = render(<WrappedComponent />);
expect(getByText("shots")).toBeTruthy();
});
});