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

Dynamic Contact Information and History #153

Merged
merged 15 commits into from
Aug 9, 2023
49 changes: 48 additions & 1 deletion __mocks__/queries/contact.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GET_CONTACTS } from '../../graphql/queries/Contact';
import { GET_CONTACTS, GET_CONTACT_INFO } from '../../graphql/queries/Contact';
import { GET_MESSAGES } from '../../graphql/queries/Chat';
import {
START_COLLECTION_FLOW,
Expand Down Expand Up @@ -953,3 +953,50 @@ export const GET_OPTIONS_MOCK = [
},
},
];

export const CONTACT_INFO_MOCK = [
{
request: {
query: GET_CONTACT_INFO,
variables: { id: '12' },
},
result: {
data: {
contact: {
contact: {
id: '1',
name: 'John Doe',
phone: '1234567890',
status: 'VALID',
language: {
label: 'English',
},
fields:
'{"name":{"value":"John","label":"Name"},"age_group":{"value":"15 to 18","label":"Age"}}',
groups: [
{
label: 'Group 1',
users: [
{
name: 'User 1',
},
{
name: 'User 2',
},
],
},
{
label: 'Group 2',
users: [
{
name: 'User 3',
},
],
},
],
},
},
},
},
},
];
61 changes: 61 additions & 0 deletions __mocks__/queries/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { GET_CONTACT_HISTORY } from '../../graphql/queries/Contact';

const mockHistory = {
contactHistory: [
{
eventDatetime: '2023-08-05T10:00:00.000Z',
eventLabel: 'Flow Started',
eventMeta: '{"flow":{"name":"FlowName1"}}',
eventType: 'SomeEventType',
id: '1',
insertedAt: '2023-08-05T10:00:00.000Z',
updatedAt: '2023-08-05T10:00:00.000Z',
},
{
eventDatetime: '2023-07-24T17:14:52Z',
eventLabel: 'Last Active flow is killed as new flow has started',
eventMeta: '{"status":"published","source":"init_context","flow_id":14}',
eventType: 'SomeOtherEventType',
id: '2',
insertedAt: '2023-07-24T17:14:52.000000Z',
updatedAt: '2023-07-24T17:14:52.000000Z',
},
],
};
// Function to generate a new item with similar properties
const createSimilarItem = (id: string) => ({
eventDatetime: '2023-08-05T10:00:00.000Z',
eventLabel: 'Flow Started',
eventMeta: '{"flow":{"name":"FlowName' + id + '"}}',
eventType: 'SomeEventType',
id: id,
insertedAt: '2023-08-05T10:00:00.000Z',
updatedAt: '2023-08-05T10:00:00.000Z',
});

// Populate the mockHistory.contactHistory array with 10 more items
for (let i = 3; i <= 10; i++) {
mockHistory.contactHistory.push(createSimilarItem(i.toString()));
}

export const GET_CONTACT_HISTORY_MOCK = {
request: {
query: GET_CONTACT_HISTORY,
variables: { opts: { order: 'ASC', limit: 10, offset: 0 }, filter: { contactId: '2' } },
},
result: {
data: mockHistory,
},
};

export const GET_EMPTY_HISTORY_MOCK = [
{
request: {
query: GET_CONTACT_HISTORY,
variables: { opts: { order: 'ASC', limit: 10, offset: 0 }, filter: { contactId: '2' } },
},
result: {
data: { contactHistory: [] },
},
},
];
28 changes: 23 additions & 5 deletions __tests__/ContactHistory.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,32 @@ import React from 'react';
import customRender from '../utils/jestRender';

import ContactHistory from '../screens/ContactHistory';
import { GET_CONTACT_HISTORY_MOCK, GET_EMPTY_HISTORY_MOCK } from '../__mocks__/queries/history';
import { waitFor } from '@testing-library/react-native';

describe('Contact History', () => {
test('renders the contact history screen', () => {
const { getByText } = customRender(<ContactHistory />);
test('renders loading indicator for no data', () => {
const { getByTestId } = customRender(<ContactHistory route={{ params: { id: '2' } }} />);
expect(getByTestId('loadingIndicator')).toBeDefined();
});

expect(getByText('Flow Started: Registration Workflow')).toBeDefined();
// expect(getByText('19/07/2023, 08:52:11')).toBeDefined();
test('render with no history data', async () => {
const { getByText } = customRender(
<ContactHistory route={{ params: { id: '2' } }} />,
GET_EMPTY_HISTORY_MOCK
);
await waitFor(async () => {
expect(getByText('No History Available')).toBeDefined();
});
});

expect(getByText('Load More')).toBeDefined();
test('renders the history list correctly', async () => {
const { getByText } = customRender(<ContactHistory route={{ params: { id: '2' } }} />, [
GET_CONTACT_HISTORY_MOCK,
]);
await waitFor(async () => {
expect(getByText('Last Active flow is killed as new flow has started')).toBeDefined();
expect(getByText('Flow Started: FlowName1')).toBeDefined();
});
});
});
44 changes: 33 additions & 11 deletions __tests__/ContactProfile.test.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import React from 'react';
import { fireEvent } from '@testing-library/react-native';
import { fireEvent, waitFor } from '@testing-library/react-native';
import customRender from '../utils/jestRender';

import ContactProfile from '../screens/ContactProfile';
import { CONTACT_INFO_MOCK } from '../__mocks__/queries/contact';

const contactMock = {
id: '12',
name: 'John Doe',
lastMessageAt: '2023-06-15',
};

const navigationMock = {
navigate: jest.fn(),
goBack: jest.fn(),
};

describe('ContactProfile', () => {
test('renders the contact profile with correct information', () => {
const { getByTestId, getByText } = customRender(
<ContactProfile route={{ params: { contact: contactMock } }} />
<ContactProfile navigation={navigationMock} route={{ params: { contact: contactMock } }} />
);

expect(getByTestId('backIcon')).toBeDefined();
Expand All @@ -32,22 +38,38 @@ describe('ContactProfile', () => {
expect(getByText('Contact History')).toBeDefined();
});

test('calls the navigation.goBack() function when the back button is pressed', () => {
const navigationMock = {
navigate: jest.fn(),
goBack: jest.fn(),
};
const { getByTestId, getByText } = customRender(
test('calls the navigation.goBack() function when the back button is pressed', async () => {
const { getByTestId } = customRender(
<ContactProfile navigation={navigationMock} route={{ params: { contact: contactMock } }} />
);

fireEvent.press(getByTestId('backIcon'));
expect(navigationMock.goBack).toHaveBeenCalled();
});

fireEvent.press(getByText('View Info'));
expect(navigationMock.navigate).toHaveBeenCalledWith('ContactInformation');
test('navigate to view info page', async () => {
const { getByText } = customRender(
<ContactProfile navigation={navigationMock} route={{ params: { contact: contactMock } }} />,
CONTACT_INFO_MOCK
);
await waitFor(async () => {
fireEvent.press(getByText('View Info'));
expect(navigationMock.navigate).toHaveBeenCalledWith('ContactInformation', {
fields: { Name: 'John', Age: '15 to 18' },
});
});
});

test('navigate to contact history page', async () => {
const { getByText } = customRender(
<ContactProfile navigation={navigationMock} route={{ params: { contact: contactMock } }} />,
CONTACT_INFO_MOCK
);
fireEvent.press(getByText('Contact History'));
expect(navigationMock.navigate).toHaveBeenCalledWith('ContactHistory');
await waitFor(async () => {
expect(navigationMock.navigate).toHaveBeenCalledWith('ContactHistory', {
id: '12',
});
});
});
});
29 changes: 21 additions & 8 deletions __tests__/MoreInfo.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,28 @@ import customRender from '../utils/jestRender';

import ContactInfo from '../screens/ContactInfo';

// Mock the navigation and route objects
const mockNavigation = { navigate: jest.fn() };
const mockFields = {
field1: 'value1',
field2: 'value2',
};

describe('More Information', () => {
test('renders the more information screen', () => {
const { getByTestId } = customRender(<ContactInfo />);
test('renders the fields', () => {
const { getByText } = customRender(
<ContactInfo navigation={mockNavigation} route={{ params: { fields: mockFields } }} />
);
expect(getByText('field1')).toBeDefined();
expect(getByText('value1')).toBeDefined();
expect(getByText('field2')).toBeDefined();
expect(getByText('value2')).toBeDefined();
});

expect(getByTestId('Provider status')).toBeDefined();
expect(getByTestId('Status')).toBeDefined();
expect(getByTestId('Role')).toBeDefined();
expect(getByTestId('Age')).toBeDefined();
expect(getByTestId('Language')).toBeDefined();
expect(getByTestId('contactStatus')).toBeDefined();
test('renders with no fields available', () => {
const { getByText } = customRender(
<ContactInfo navigation={mockNavigation} route={{ params: { fields: {} } }} />
);
expect(getByText('No Fields Available')).toBeDefined();
});
});
2 changes: 1 addition & 1 deletion __tests__/Notifications.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('Notifications Screen', () => {
expect(logSpy).toHaveBeenCalledWith('Test error');
});
logSpy.mockRestore();
});
}, 5000);

test('renders the Notification header search', async () => {
const { getByTestId } = customRender(
Expand Down
4 changes: 4 additions & 0 deletions components/navigation/CustomDrawer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useContext, useState, useEffect } from 'react';
import { View, Text, Image, Pressable, StyleSheet } from 'react-native';
import { DrawerContentScrollView, DrawerItemList } from '@react-navigation/drawer';
import { useApolloClient } from '@apollo/client';

import Wallet from './Wallet';
import { Feather } from '@expo/vector-icons';
Expand All @@ -9,11 +10,13 @@ import { COLORS, SCALE, SIZES } from '../../constants';
import AuthContext from '../../config/AuthContext';
import AxiosService from '../../config/axios';


type DrawerContentProps = {
navigation: undefined;
};

const CustomDrawer: React.FC<DrawerContentProps> = (props) => {
const client = useApolloClient();
const [orgName, setOrgName] = useState('');
const { setToken } = useContext(AuthContext);

Expand All @@ -34,6 +37,7 @@ const CustomDrawer: React.FC<DrawerContentProps> = (props) => {
const LogoutHandler = async () => {
await Storage.removeData('glific_session');
await Storage.removeData('glific_user');
client.clearStore();
setToken(null);
};

Expand Down
21 changes: 14 additions & 7 deletions config/apollo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,20 @@ const refreshLink = new TokenRefreshLink({
const renewalToken = parsedSessionValue.renewal_token;

const Client = await AxiosService.createAxiosInstance();
const response = await Client.post('/v1/session/renew', null, {
headers: {
Authorization: renewalToken,
},
});
if (response.status === 200) {
return response.data;
try {
const response = await Client.post('/v1/session/renew', null, {
headers: {
Authorization: renewalToken,
},
});
if (response.status === 200) {
return response.data;
}
} catch (err: any) {
if (err.response.status === 401) {
await Storage.removeData('glific_session');
await Storage.removeData('glific_user');
}
}
return null;
},
Expand Down
6 changes: 3 additions & 3 deletions config/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class AxiosService {

static async createAxiosInstance(): Promise<AxiosInstance> {
if (!AxiosService.baseURL) {
const orgValue = await Storage.getData('glific_orgnisation');
const orgValue = await Storage.getData('glific_organisation');
if (orgValue) {
const parsedOrgValue = JSON.parse(orgValue);
AxiosService.baseURL = parsedOrgValue.url;
Expand All @@ -21,11 +21,11 @@ class AxiosService {

static async updateServerURL(url: string): Promise<void> {
AxiosService.baseURL = url;
const orgValue = await Storage.getData('glific_orgnisation');
const orgValue = await Storage.getData('glific_organisation');
if (orgValue) {
const parsedOrgValue = JSON.parse(orgValue);
const updatedOrgValue = JSON.stringify({ ...parsedOrgValue, url });
await Storage.storeData('glific_orgnisation', updatedOrgValue);
await Storage.storeData('glific_organisation', updatedOrgValue);
}
}

Expand Down
Loading