diff --git a/component/with-query-handling.tsx b/component/with-query-handling.tsx new file mode 100644 index 0000000..9771452 --- /dev/null +++ b/component/with-query-handling.tsx @@ -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; + 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 Loading...; + } + if (error) { + return Error: {error.message}; + } + + const specificData = data[dataKey]; + return ; + }; +} + +export default withQueryHandling; diff --git a/test/component/with-query-handling.test.tsx b/test/component/with-query-handling.test.tsx new file mode 100644 index 0000000..970994d --- /dev/null +++ b/test/component/with-query-handling.test.tsx @@ -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 }) => ( + {data ? data : "No Data"} +); + +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(); + 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(); + expect(getByText("shots")).toBeTruthy(); + }); +});