Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed multiple profile issue #3076

Merged
merged 10 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/containers/Form/FormLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ export const FormLayout = ({
}
}, [advanceSearch]);

useEffect(() => {
Copy link
Contributor

@kurund kurund Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's discuss this during stand up.

if (entityId) {
refetch();
}
}, [entityId]);

const capitalListItemName = listItemName[0].toUpperCase() + listItemName.slice(1);
let item: any = null;

Expand Down Expand Up @@ -221,7 +227,7 @@ export const FormLayout = ({
variables = params.type ? { shortcode: params.type } : false;
}

const { loading, error } = useQuery(getItemQuery, {
const { loading, error, refetch } = useQuery(getItemQuery, {
variables,
skip: !itemId,
fetchPolicy: getQueryFetchPolicy,
Expand Down
75 changes: 57 additions & 18 deletions src/containers/Profile/Contact/ContactProfile.test.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
import { render, waitFor } from '@testing-library/react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import { vi } from 'vitest';

import { LOGGED_IN_USER_MOCK } from 'mocks/Contact';
import { LOGGED_IN_USER_MOCK, multiple_profile_mock } from 'mocks/Contact';
import { ContactProfile } from './ContactProfile';
import { mocks as historyMock } from './ContactHistory/ContactHistory.test';
import { MemoryRouter } from 'react-router-dom';

vi.mock('react-router-dom', async () => {
const actual: any = await vi.importActual('react-router-dom');
return {
...actual,
useParams: () => ({ id: '1' }),
};
});
import { MemoryRouter, Route, Routes } from 'react-router-dom';

describe('contact profile', () => {
describe('contact profile with single profile', () => {
const mocks = [...LOGGED_IN_USER_MOCK, ...historyMock];

const contactProfile = (
<MemoryRouter>
<MemoryRouter initialEntries={['/contact-profile/1']}>
<MockedProvider mocks={mocks} addTypename={false}>
<ContactProfile />
<Routes>
<Route path="contact-profile/:id/*" element={<ContactProfile />} />
</Routes>
</MockedProvider>
</MemoryRouter>
);

test('contact profile should render', async () => {
const { getByText, getAllByRole } = render(contactProfile);
await waitFor(() => {
expect(getByText('Profile')).toBeInTheDocument();
});

await waitFor(() => {
expect(getByText('Loading...')).toBeInTheDocument();
Expand All @@ -44,5 +34,54 @@ describe('contact profile', () => {
await waitFor(() => {
expect(getAllByRole('textbox')[0]).toHaveValue('N/A');
});

fireEvent.click(getByText('History'));

await waitFor(() => {
expect(screen.getByText('Removed from collection: "Optout contacts"')).toBeInTheDocument();
});

fireEvent.click(getByText('Details'));

await waitFor(() => {
expect(screen.getByText('Status')).toBeInTheDocument();
expect(screen.getByText('Collections')).toBeInTheDocument();
});
});
});

describe('contact profile with no profiles', () => {
const wrapper = (
<MockedProvider mocks={multiple_profile_mock}>
<MemoryRouter initialEntries={['/contact-profile/2']}>
<Routes>
<Route path="contact-profile/:id/*" element={<ContactProfile />} />
</Routes>
</MemoryRouter>
</MockedProvider>
);

test('should switch profile', async () => {
render(wrapper);

await waitFor(() => {
expect(screen.getByText('Contact Profile')).toBeInTheDocument();
});

await waitFor(() => {
expect(screen.getByText('Loading...')).toBeInTheDocument();
});

//should show active profile first
await waitFor(() => {
expect(screen.getAllByRole('textbox')[0]).toHaveValue('profile name 2');
});

fireEvent.click(screen.getAllByTestId('profileHeader')[1]);

//should show active profile first
await waitFor(() => {
expect(screen.getAllByRole('textbox')[0]).toHaveValue('profile name 1');
});
});
});
6 changes: 2 additions & 4 deletions src/containers/Profile/Contact/ContactProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { useTranslation } from 'react-i18next';
import CollapseIcon from '../../../assets/images/icons/Collapse.svg?react';
import ExpandIcon from '../../../assets/images/icons/Expand.svg?react';
import { getContactStatus, getDisplayName } from 'common/utils';
import { getOrganizationServices } from 'services/AuthService';
import { GET_CONTACT_DETAILS, GET_CONTACT_PROFILES } from 'graphql/queries/Contact';
import { Loading } from 'components/UI/Layout/Loading/Loading';
import { AvatarDisplay } from 'components/UI/AvatarDisplay/AvatarDisplay';
Expand All @@ -23,12 +22,10 @@ export const ContactProfile = () => {
const [showProfileSection, setShowProfileSection] = useState('profile');
const { t } = useTranslation();

const isContactProfileEnabled = getOrganizationServices('contactProfileEnabled');
const { loading, data } = useQuery(GET_CONTACT_DETAILS, { variables: { id: params.id } });

const { loading: profileLoading, data: profileData } = useQuery(GET_CONTACT_PROFILES, {
variables: { filter: { contactId: params.id } },
skip: !isContactProfileEnabled,
fetchPolicy: 'network-only',
});

Expand All @@ -54,7 +51,7 @@ export const ContactProfile = () => {

let selectedProfile;

if (isContactProfileEnabled && profileData && profileData.profiles.length > 0) {
if (profileData && profileData.profiles.length > 0) {
selectedProfile = profileData.profiles.filter(
(profile: any) => profile.id === selectedProfileId
);
Expand Down Expand Up @@ -105,6 +102,7 @@ export const ContactProfile = () => {
return (
<React.Fragment key={id}>
<div
data-testid="profileHeader"
className={styles.ProfileHeader}
onClick={() => {
setSelectedProfileId(`${id}`);
Expand Down
29 changes: 15 additions & 14 deletions src/containers/Profile/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ import { CONTACT_STATUS, PROVIDER_STATUS } from 'common/constants';
import { FormLayout } from 'containers/Form/FormLayout';
import { Input } from 'components/UI/Form/Input/Input';
import { Loading } from 'components/UI/Layout/Loading/Loading';
import { GET_CONTACT } from 'graphql/queries/Contact';
import { GET_CONTACT, GET_PROFILE } from 'graphql/queries/Contact';
import {
CREATE_CONTACT,
UPDATE_CONTACT,
DELETE_CONTACT,
DELETE_CONTACT_PROFILE,
} from 'graphql/mutations/Contact';
import { GET_CURRENT_USER } from 'graphql/queries/User';
import { getOrganizationServices } from 'services/AuthService';
import { getDisplayName, isSimulator } from 'common/utils';
import { AutoComplete } from 'components/UI/Form/AutoComplete/AutoComplete';

Expand All @@ -43,11 +42,10 @@ export const Profile = ({
const [languageId, setLanguageId] = useState('');
const [hideRemoveBtn, setHideRemoveBtn] = useState(false);
const { t } = useTranslation();
const isContactProfileEnabled = getOrganizationServices('contactProfileEnabled');
const hasMultipleProfiles = multiProfileAttributes?.selectedProfile;

const queries = {
getItemQuery: GET_CONTACT,
getItemQuery: hasMultipleProfiles ? GET_PROFILE : GET_CONTACT,
createItemQuery: CREATE_CONTACT,
updateItemQuery: UPDATE_CONTACT,
deleteItemQuery: hasMultipleProfiles ? DELETE_CONTACT_PROFILE : DELETE_CONTACT,
Expand All @@ -58,16 +56,12 @@ export const Profile = ({
const { data, loading } = useQuery(GET_CURRENT_USER);

const updateName = () => {
if (!isContactProfileEnabled || !hasMultipleProfiles) {
if (!hasMultipleProfiles) {
return;
}
const { selectedProfile } = multiProfileAttributes;
const { selectedProfile, selectedProfileId } = multiProfileAttributes;

if (!selectedProfile) {
return;
}

if (selectedProfile.id === multiProfileAttributes.activeProfileId) {
if (selectedProfileId === multiProfileAttributes.activeProfileId) {
setName(`${selectedProfile.name} (currently active)`);
} else {
setName(selectedProfile.name);
Expand Down Expand Up @@ -103,6 +97,7 @@ export const Profile = ({
bspStatus: bspStatusValue,
language: languageIdValue,
fields: fieldsValue,
contact: contactDetails,
}: any) => {
updateName();
let hideDeleteButton = false;
Expand All @@ -126,9 +121,15 @@ export const Profile = ({
hideDeleteButton = organizationPhone === currentUserPhone;
}

if (hasMultipleProfiles) {
setStatus(contactDetails?.status);
setBspStatus(contactDetails?.bspStatus);
} else {
setStatus(statusValue);
setBspStatus(bspStatusValue);
}

setName(displayName);
setStatus(statusValue);
setBspStatus(bspStatusValue);
setHideRemoveBtn(hideDeleteButton);
setLanguageId(languageIdValue.id);
};
Expand Down Expand Up @@ -199,7 +200,7 @@ export const Profile = ({
dialogMessage={dialogMessage}
formFields={formFields}
redirectionLink={redirectionLink}
listItem="contact"
listItem={hasMultipleProfiles ? 'profile' : 'contact'}
icon={profileIcon}
afterDelete={afterDelete}
type={type}
Expand Down
22 changes: 22 additions & 0 deletions src/graphql/queries/Contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,25 @@ export const GET_CONTACT_PROFILES = gql`
}
}
`;

export const GET_PROFILE = gql`
query getProfile($id: ID!) {
profile(id: $id) {
profile {
id
name
fields
type
language {
label
id
}
contact {
status
bspStatus
settings
}
}
}
}
`;
Loading
Loading