diff --git a/src/screens/UserPortal/Organizations/Organizations.spec.tsx b/src/screens/UserPortal/Organizations/Organizations.spec.tsx index 36940863102..4c8c39a2721 100644 --- a/src/screens/UserPortal/Organizations/Organizations.spec.tsx +++ b/src/screens/UserPortal/Organizations/Organizations.spec.tsx @@ -6,6 +6,7 @@ import userEvent from '@testing-library/user-event'; import { USER_CREATED_ORGANIZATIONS, USER_JOINED_ORGANIZATIONS, + USER_JOINED_ORGANIZATIONS_PG, USER_ORGANIZATION_CONNECTION, } from 'GraphQl/Queries/Queries'; import { Provider } from 'react-redux'; @@ -317,14 +318,224 @@ const MOCKS = [ }, }, }, + { + request: { + query: USER_JOINED_ORGANIZATIONS_PG, + variables: { + id: getItem('userId'), + first: 5, + }, + }, + result: { + data: { + UserJoinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'anyOrganization1', + description: 'desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + userRegistrationRequired: true, + members: [], + admins: [], + membershipRequests: [], + isJoined: false, + }, + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af3', + image: '', + name: 'anyOrganization2', + description: 'desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + userRegistrationRequired: true, + members: [], + admins: [], + membershipRequests: [], + isJoined: false, + }, + ], + }, + }, + }, + // New mock for search query + { + request: { + query: USER_JOINED_ORGANIZATIONS_PG, + variables: { + id: getItem('userId'), + first: 5, + filter: '2', + }, + }, + result: { + data: { + UserJoinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af3', + image: '', + name: 'anyOrganization2', + description: 'desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + userRegistrationRequired: true, + members: [], + admins: [], + membershipRequests: [], + isJoined: false, + }, + ], + }, + }, + }, + // Mock for empty search (when search is cleared) + { + request: { + query: USER_JOINED_ORGANIZATIONS_PG, + variables: { + id: getItem('userId'), + first: 5, + filter: '', + }, + }, + result: { + data: { + UserJoinedOrganizations: [ + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'anyOrganization1', + description: 'desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + userRegistrationRequired: true, + members: [], + admins: [], + membershipRequests: [], + isJoined: false, + }, + { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af3', + image: '', + name: 'anyOrganization2', + description: 'desc', + address: { + city: 'abc', + countryCode: '123', + postalCode: '456', + state: 'def', + dependentLocality: 'ghi', + line1: 'asdfg', + line2: 'dfghj', + sortingCode: '4567', + }, + userRegistrationRequired: true, + members: [], + admins: [], + membershipRequests: [], + isJoined: false, + }, + ], + }, + }, + }, + { + request: { + query: USER_JOINED_ORGANIZATIONS, + variables: { + id: getItem('userId'), + }, + }, + result: { + data: { + users: [ + { + user: { + organizationsWhereMember: { + edges: [ + { + node: { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'Test Edge Org', + description: 'Test Description', + address: { + city: 'Test City', + countryCode: '123', + postalCode: '456', + state: 'Test State', + dependentLocality: 'Test Locality', + line1: 'Test Line 1', + line2: 'Test Line 2', + sortingCode: '4567', + }, + createdAt: '1234567890', + userRegistrationRequired: true, + creator: { + __typename: 'User', + name: 'Test Creator', + }, + members: [ + { + _id: 'member1', + user: { + _id: getItem('userId'), + }, + }, + ], + admins: [], + membershipRequests: [], + }, + }, + ], + }, + }, + }, + ], + }, + }, + }, ]; -/** - * Custom Mock Link for handling static GraphQL mocks. - */ - -const link = new StaticMockLink(MOCKS, true); - async function wait(ms = 100): Promise { await act(() => { return new Promise((resolve) => { @@ -380,16 +591,40 @@ describe('Testing Organizations Screen [User Portal]', () => { , ); + // Wait for initial data load await wait(); + + // Verify initial state + expect(screen.getByText('anyOrganization1')).toBeInTheDocument(); + expect(screen.getByText('anyOrganization2')).toBeInTheDocument(); + + // Perform search + const searchInput = screen.getByTestId('searchInput'); + await userEvent.type(searchInput, '2'); + + // Get and click search button const searchBtn = screen.getByTestId('searchBtn'); - await userEvent.type(screen.getByTestId('searchInput'), '2{enter}'); - await wait(); + await userEvent.click(searchBtn); - expect(screen.queryByText('anyOrganization2')).toBeInTheDocument(); + // Wait for search results to update + await wait(); - await userEvent.clear(screen.getByTestId('searchInput')); + // Clear search + await userEvent.clear(searchInput); await userEvent.click(searchBtn); + + // Wait again for results to update await wait(); + + // Perform search again + await userEvent.type(searchInput, '2'); + await userEvent.keyboard('{Enter}'); + + // Wait for final search results + await wait(); + + // Verify final state + expect(screen.getByText('anyOrganization2')).toBeInTheDocument(); }); /** @@ -450,7 +685,7 @@ describe('Testing Organizations Screen [User Portal]', () => { * Test case to check if the "Join Now" button renders correctly on the page. */ - test('Join Now button render correctly', async () => { + test('Join Now button renders correctly', async () => { render( @@ -463,11 +698,16 @@ describe('Testing Organizations Screen [User Portal]', () => { , ); - await wait(); + // Wait for organizations to load + await waitFor(() => { + expect(screen.getByText('anyOrganization1')).toBeInTheDocument(); + }); - // Assert "Join Now" button - const joinNowButtons = screen.getAllByTestId('joinBtn'); - expect(joinNowButtons.length).toBeGreaterThan(0); + // Check for join buttons + await waitFor(() => { + const joinButtons = screen.getAllByTestId('joinBtn'); + expect(joinButtons.length).toBe(2); // We expect 2 buttons since we have 2 organizations + }); }); test('Mode is changed to created organisations', async () => { @@ -593,4 +833,101 @@ describe('Testing Organizations Screen [User Portal]', () => { const searchInput = screen.getByPlaceholderText('Search Organization'); expect(searchInput).toBeInTheDocument(); }); + const link = new StaticMockLink(MOCKS, true); +}); + +describe('Testing Organizations Edge/Node Data Structure', async () => { + test('processes edge/node data structure correctly', async () => { + const TEST_USER_NAME = 'Noble Mittal'; + + beforeEach(() => { + setItem('name', TEST_USER_NAME); + }); + + const EDGE_MOCK = { + request: { + query: USER_JOINED_ORGANIZATIONS_PG, + variables: { + id: getItem('userId'), + first: 5, + filter: '', + }, + }, + result: { + data: { + user: { + organizationsWhereMember: { + edges: [ + { + node: { + __typename: 'Organization', + _id: '6401ff65ce8e8406b8f07af2', + image: '', + name: 'Test Edge Org', + description: 'Test Description', + address: { + city: 'Test City', + countryCode: '123', + postalCode: '456', + state: 'Test State', + dependentLocality: 'Test Locality', + line1: 'Test Line 1', + line2: 'Test Line 2', + sortingCode: '4567', + }, + userRegistrationRequired: true, + members: [ + { + _id: 'member1', + user: { + _id: getItem('userId'), + }, + }, + ], + admins: [], + membershipRequests: [], + }, + }, + ], + }, + }, + }, + }, + }; + const linkWithEdge = new StaticMockLink([EDGE_MOCK], true); + render( + + + + + + + + + , + ); + + // Wait for loading state + expect(screen.getByText('Loading...')).toBeInTheDocument(); + + // Wait for initial load and UI interactions + await waitFor( + () => { + expect(screen.getByTestId('modeChangeBtn')).toBeInTheDocument(); + }, + { timeout: 2000 }, + ); + + // Change mode to test edge/node data structure + await userEvent.click(screen.getByTestId('modeChangeBtn')); + await userEvent.click(screen.getByTestId('modeBtn0')); + + // Wait for the query to complete and data to be displayed + await waitFor( + () => { + expect(screen.getByText('Test Edge Org')).toBeInTheDocument(); + }, + { timeout: 2000 }, + ); + }); }); diff --git a/src/screens/UserPortal/Organizations/Organizations.tsx b/src/screens/UserPortal/Organizations/Organizations.tsx index 8d3eb19d5c4..933cde288dd 100644 --- a/src/screens/UserPortal/Organizations/Organizations.tsx +++ b/src/screens/UserPortal/Organizations/Organizations.tsx @@ -4,7 +4,7 @@ import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import { USER_CREATED_ORGANIZATIONS, USER_JOINED_ORGANIZATIONS, - USER_ORGANIZATION_CONNECTION, + USER_JOINED_ORGANIZATIONS_PG, } from 'GraphQl/Queries/Queries'; import PaginationList from 'components/Pagination/PaginationList/PaginationList'; import OrganizationCard from 'components/UserPortal/OrganizationCard/OrganizationCard'; @@ -125,7 +125,7 @@ export default function organizations(): JSX.Element { const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(5); const [organizations, setOrganizations] = React.useState([]); - const [filterName, setFilterName] = React.useState(''); + const [, setFilterName] = React.useState(''); const [mode, setMode] = React.useState(0); const modes = [ @@ -140,8 +140,8 @@ export default function organizations(): JSX.Element { data, refetch, loading: loadingOrganizations, - } = useQuery(USER_ORGANIZATION_CONNECTION, { - variables: { filter: filterName }, + } = useQuery(USER_JOINED_ORGANIZATIONS_PG, { + variables: { id: userId, first: rowsPerPage, filter: '' }, }); const { data: joinedOrganizationsData } = useQuery( @@ -227,7 +227,7 @@ export default function organizations(): JSX.Element { */ useEffect(() => { if (data) { - const organizations = data.organizationsConnection.map( + const organizations = data?.UserJoinedOrganizations?.map( (organization: InterfaceOrganization) => { let membershipRequestStatus = ''; if ( @@ -255,19 +255,22 @@ export default function organizations(): JSX.Element { */ useEffect(() => { if (mode === 0) { - if (data) { - const organizations = data.organizationsConnection.map( - (organization: InterfaceOrganization) => { + if (data?.user?.organizationsWhereMember?.edges) { + const organizations = data.user.organizationsWhereMember.edges.map( + (edge: { node: InterfaceOrganization }) => { + const organization = edge.node; let membershipRequestStatus = ''; + if ( - organization.members.find( + Array.isArray(organization.members) && + organization.members.some( (member: { _id: string }) => member._id === userId, ) ) membershipRequestStatus = 'accepted'; else if ( - organization.membershipRequests.find( - (request: { user: { _id: string } }) => + organization.membershipRequests?.some( + (request: { _id: string; user: { _id: string } }) => request.user._id === userId, ) ) @@ -282,9 +285,9 @@ export default function organizations(): JSX.Element { setOrganizations(organizations); } } else if (mode === 1) { - if (joinedOrganizationsData && joinedOrganizationsData.users.length > 0) { + if (joinedOrganizationsData?.users?.[0]?.user?.joinedOrganizations) { const organizations = - joinedOrganizationsData.users[0]?.user?.joinedOrganizations.map( + joinedOrganizationsData.users[0].user.joinedOrganizations.map( (org: InterfaceOrganization) => ({ ...org, membershipRequestStatus: 'accepted', @@ -295,11 +298,11 @@ export default function organizations(): JSX.Element { } } else if (mode === 2) { if ( - createdOrganizationsData && - createdOrganizationsData.users.length > 0 + createdOrganizationsData?.users?.[0]?.appUserProfile + ?.createdOrganizations ) { const organizations = - createdOrganizationsData.users[0]?.appUserProfile?.createdOrganizations.map( + createdOrganizationsData.users[0].appUserProfile.createdOrganizations.map( (org: InterfaceOrganization) => ({ ...org, membershipRequestStatus: 'accepted',