import { useState } from 'react'; import { render, waitFor, fireEvent } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { server } from "@availity/mock/src/lib/server"; import { Spaces, useSpaces, useSpacesContext } from '..'; beforeAll(() => { // Start the interception. server.listen(); }); afterEach(() => { // Remove any handlers you may have added // in individual tests (runtime handlers). server.resetHandlers(); }); afterAll(() => { // Disable request interception and clean up. server.close(); }); describe('Spaces', () => { it('provides correct spaces from props and from avWebQL', async () => { const queryClient = new QueryClient(); // Create a space component that renders "Space is in provider" if the space is in the provider and "Space is not in provider" if it is not the provider const SpaceComponent = ({ spaceId }: { spaceId: string }) => { const space = useSpaces(spaceId); return (
{space && space.length > 0 ? `Space ${spaceId} is in provider` : `Space ${spaceId} is not in provider`}
); }; // Create component that renders a SpaceComponent for ids 1, 2, and 3 const MyComponent = () => { const [spaceIds, setSpaceIds] = useState(['1', '3']); return ( ); }; const { container, getByText } = render(); // Check that space 1 (fetched from avWebQL) is accessible by spaces provider await waitFor(() => getByText('Space 1 is in provider')); expect(getByText('Space 1 is in provider')).toBeDefined(); // Check that space 2 (not provided) is not accessible by spaces provider await waitFor(() => getByText('Space 2 is not in provider')); expect(getByText('Space 2 is not in provider')).toBeDefined(); // Check that space 3 (provided by props) is accessible by spaces provider await waitFor(() => getByText('Space 3 is in provider')); expect(getByText('Space 3 is in provider')).toBeDefined(); // Check that avWebQL was only queried for space 1 because space 3 was provided by props // Click button that adds another space id, "2", to the provider const button = container.querySelector('#add-spaceid-btn'); if (button) fireEvent.click(button); // // Check that space 1 (fetched from avWebQL) is still accessible by spaces provider await waitFor(() => getByText('Space 1 is in provider')); expect(getByText('Space 1 is in provider')).toBeDefined(); // // Check that space 2 (now fetched from avWebQL) is now accessible by spaces provider await waitFor(() => getByText('Space 2 is in provider')); expect(getByText('Space 2 is in provider')).toBeDefined(); // // Check that space 3 (provided by props) is still accessible by spaces provider await waitFor(() => getByText('Space 3 is in provider')); expect(getByText('Space 3 is in provider')).toBeDefined(); }); }); it('toggles whether the spaces provider is loading', async () => { const queryClient = new QueryClient(); const fn = vi.fn(); // Create component to call mock function const SpaceComponent = ({ spaceId }: { spaceId: string }) => { const space = useSpaces(spaceId); const { loading } = useSpacesContext(); if (loading) fn(); // Should be called when we fetch spaces from avWebQL gets executed return loading ? null : ( {space?.[0] ? `Space ${space[0].id}` : 'No Space '} ); }; // Create component that renders a SpaceComponent for the current space id const MyComponent = () => { const [spaceId, setSpaceId] = useState(['1']); return ( ); }; const { container, getByText } = render(); expect(fn).toHaveBeenCalled(); await waitFor(() => getByText('Space 1')); // Add a space id const button = container.querySelector('#add-spaceid-btn'); if (button) fireEvent.click(button); expect(fn).toHaveBeenCalled(); await waitFor(() => getByText('Space 2')); }); describe('useSpaces', () => { // Create a spaces component that renders ids passed in const SpacesComponent = ({ ids = [] }: { ids?: string[] }) => { const spaces = useSpaces(...ids) || []; const dataTestIdSuffix = ids && ids.length > 0 ? ids.join('-') : 'all-spaces'; return (
{spaces.map((spc) => `Id: ${spc.id} `)}
); }; it('returns spaces by id', async () => { const queryClient = new QueryClient(); const { container } = render( ); // Check that all spaces get returned when no ids get passed to useSpaces hook const allSpaces = await waitFor(() => container.querySelector('#spaces-for-all-spaces')); await waitFor(() => expect(allSpaces?.textContent).toBe('Id: 1 Id: 2 Id: 3 ')); // Check that spaces for ids get returned when ids passed to useSpaces hook const specificSpaces = await waitFor(() => container.querySelector('#spaces-for-2-3')); expect(specificSpaces?.textContent).toBe('Id: 2 Id: 3 '); }); it('returns spaces by configurationId', async () => { const queryClient = new QueryClient(); const { getByText } = render( ); // Check that all spaces get returned when no configurationIds get passed to useSpaces hook await waitFor(() => getByText('Id: 11 Id: 22 Id: 33')); // Check that spaces for configurationIds get returned when configurationIds passed to useSpaces hook await waitFor(() => getByText('Id: 22 Id: 33')); }); it('returns all matching spaces when searching by payerId', async () => { const queryClient = new QueryClient(); const { getByText } = render( ); // Check that spaces for payer ids get returned when ids passed to useSpaces hook await waitFor(() => getByText('Id: 11 Id: 22')); await waitFor(() => getByText('Id: 11 Id: 22 Id: 33')); }); it('renders with warning when returning all spaces because no ids were passed in', async () => { const consoleWarnMock = vi.spyOn(console, 'warn').mockImplementation(() => {}); const SpacesComponent = ({ ids = [] }) => { const spaces = useSpaces(...ids) || []; const dataTestIdSuffix = ids && ids.length > 0 ? ids.join('-') : 'all-spaces'; return (
{spaces.map((spc) => `Id: ${spc && spc.id} `)}
); }; const queryClient = new QueryClient(); const { container } = render( ); await waitFor(() => container.querySelector('#spaces-for-all-spaces')); expect(consoleWarnMock).toHaveBeenCalled(); expect(consoleWarnMock.mock.calls[0][0]).toBe('You did not pass in an ID to find a space, returning all spaces.'); consoleWarnMock.mockRestore(); }); }); it('returns first payer space with when no spaceId passed', async () => { // Create component that renders a SpaceComponent for the current space id const SpaceComponent = () => { const spaces = useSpaces() || []; return (
{spaces[0]?.name}
); }; const queryClient = new QueryClient(); const { container, getByText } = render( ); const spc1 = await waitFor(() => container.querySelector('#space-1')); const spc2 = await waitFor(() => getByText('Space 1')); expect(spc1).toBeDefined(); expect(spc2).toBeDefined(); }); describe('ID validation', () => { let mockFetchAllSpaces: ReturnType; beforeEach(async () => { const spacesData = await import('./spaces-data'); mockFetchAllSpaces = vi.spyOn(spacesData, 'fetchAllSpaces').mockResolvedValue([]); }); afterEach(() => { mockFetchAllSpaces.mockRestore(); }); it('filters invalid spaceIds before querying', async () => { mockFetchAllSpaces.mockResolvedValue([]); const queryClient = new QueryClient(); render(
test
); await waitFor(() => { expect(mockFetchAllSpaces).toHaveBeenCalledWith( expect.objectContaining({ variables: expect.objectContaining({ ids: ['valid-id'], }), }) ); }); }); it('avoids querying if no valid spaceIds exist', async () => { mockFetchAllSpaces.mockResolvedValue([]); const queryClient = new QueryClient(); render(
test
); await waitFor(() => { expect(mockFetchAllSpaces).not.toHaveBeenCalled(); }); }); it('filters invalid payerIds before querying', async () => { mockFetchAllSpaces.mockResolvedValue([]); const queryClient = new QueryClient(); render(
test
); await waitFor(() => { expect(mockFetchAllSpaces).toHaveBeenCalledWith( expect.objectContaining({ variables: expect.objectContaining({ payerIDs: ['valid-payer'], }), }) ); }); }); it('avoids querying if no valid payerIds exist', async () => { mockFetchAllSpaces.mockResolvedValue([]); const queryClient = new QueryClient(); render(
test
); await waitFor(() => { expect(mockFetchAllSpaces).not.toHaveBeenCalled(); }); }); });