contacts screen
unknown
plain_text
5 years ago
20 kB
10
Indexable
/* ------------------------ Imports ------------------------ */
import { FlatList, Platform, TouchableOpacity } from 'react-native'
import React, { useCallback } from 'react'
import { mount } from 'enzyme'
import { MockedProvider } from '@apollo/client/testing'
import ContactScreen from '../../../App/Containers/Onboarding/ContactsScreen'
import { MediumButton } from '../../../App/Components/Buttons/MediumButton'
import ClickableText from '../../../App/Components/ClickableText'
import Header from '../../../App/Components/Header'
import Users from '../../../App/Components/ListOfFriends/ListOfFriends'
import { LargeButton } from '../../../App/Components/Buttons/LargeButton'
import Modal from 'react-native-modal'
import { useIsFocused } from '@react-navigation/native'
// Importing mutations
import mutations from '../../../src/graphql/mutations'
import AsyncStorage from '@react-native-community/async-storage'
import Contacts from 'react-native-contacts'
import { GraphQLError } from 'graphql'
import { number } from 'prop-types'
jest.mock('@react-native-community/async-storage')
/* ------------------------ Props ------------------------ */
const createTestProps = (props) => ({
navigation: {
navigate: jest.fn(),
goBack: jest.fn()
},
...props
})
/* ------------------------ Constants ------------------------ */
let addFriendMutation = false
let addContactsMutation = false
let sendInviteMutation = false
const CONTACTS_INPUT = [
{
name: 'Carl Jung',
email: 'carl-jung@example.com',
contactNumber: '(555) 555-5555',
extraInfo: null,
recordId: '1'
},
{
name: 'Sher Lock',
email: 'sher@example.com',
contactNumber: '(999) 999-9999',
extraInfo: null,
recordId: '2'
},
{
name: 'abc',
email: null,
contactNumber: '(111) 111-1111',
extraInfo: null,
recordId: '3'
},
{
name: 'Without Phone',
email: 'withoutphone@example.com',
contactNumber: null,
extraInfo: null,
recordId: '4'
}
]
const CONTACTS_OUTPUT = [
{
name: 'Carl Jung',
email: 'carl-jung@example.com',
contactNumber: '(555) 555-5555',
userId: '1',
contactId: '123',
existingUserId: '001'
},
{
name: 'Sher Lock',
email: 'sher@example.com',
contactNumber: '(999) 999-9999',
userId: '1',
contactId: '456',
existingUserId: null
},
{
name: 'abc',
email: null,
contactNumber: '(111) 111-1111',
userId: '1',
contactId: '789',
existingUserId: null
},
{
name: 'Without Phone',
email: 'withoutphone@example.com',
contactNumber: null,
userId: '1',
contactId: '1409',
existingUserId: null
}
]
/* ------------------------ Mocks ------------------------ */
const mocks = [
{
request: {
query: mutations.User.ADD_FRIEND,
variables: {
users: ['001']
}
},
result: () => {
addFriendMutation = true
return {
data: {
addFriend: true
}
}
}
},
{
request: {
query: mutations.Onboarding.ADD_CONTACTS,
variables: {
contacts: CONTACTS_INPUT
}
},
result: () => {
addContactsMutation = true
return {
data: {
AddContacts: CONTACTS_OUTPUT
}
}
}
},
{
request: {
query: mutations.Onboarding.SEND_INVITE,
variables: {
contactIds: ['456'],
inviteMode: 'EMAIL'
}
},
result: () => {
sendInviteMutation = true
return {
data: {
SendInvite: true
}
}
}
},
{
request: {
query: mutations.Onboarding.SEND_INVITE,
variables: {
contactIds: ['456', '1409'],
inviteMode: 'EMAIL'
}
},
result: () => {
sendInviteMutation = true
return {
data: {
SendInvite: true
}
}
}
},
{
request: {
query: mutations.Onboarding.SEND_INVITE,
variables: {
contactIds: ['789'],
inviteMode: 'PHONE'
}
},
result: () => {
sendInviteMutation = true
return {
data: {
SendInvite: true
}
}
}
}
]
const defaultOutput = {
data: {
AddContacts: CONTACTS_OUTPUT
}
}
const createCustomMock = (contactsOutput = defaultOutput) => {
return [
{
request: {
query: mutations.User.ADD_FRIEND,
variables: {
users: ['001']
}
},
result: () => {
addFriendMutation = true
return {
data: {
addFriend: true
}
}
}
},
{
request: {
query: mutations.Onboarding.ADD_CONTACTS,
variables: {
contacts: CONTACTS_INPUT
}
},
result: () => {
addContactsMutation = true
return contactsOutput
}
},
{
request: {
query: mutations.Onboarding.SEND_INVITE,
variables: {
contactIds: ['456'],
inviteMode: 'EMAIL'
}
},
result: () => {
sendInviteMutation = true
return {
data: {
SendInvite: true
}
}
}
},
{
request: {
query: mutations.Onboarding.SEND_INVITE,
variables: {
contactIds: ['456', '1409'],
inviteMode: 'EMAIL'
}
},
result: () => {
sendInviteMutation = true
return {
data: {
SendInvite: true
}
}
}
},
{
request: {
query: mutations.Onboarding.SEND_INVITE,
variables: {
contactIds: ['789'],
inviteMode: 'PHONE'
}
},
result: () => {
sendInviteMutation = true
return {
data: {
SendInvite: true
}
}
}
}
]
}
const OriginalImplementations = {
getContactsByPhoneNumber: (number, callback) => callback(null, Contacts.DUMMY),
getAll: (callback) => {
callback(null, Contacts.DUMMY)
},
getContactsByEmailAddress: (number, callback) => callback(null, Contacts.DUMMY)
}
function resetImplementations() {
Contacts.getContactsByEmailAddress.mockImplementation(
OriginalImplementations.getContactsByPhoneNumber
)
Contacts.getAll.mockImplementation(OriginalImplementations.getContactsByPhoneNumber)
Contacts.getAll.mockImplementation(OriginalImplementations.getAll)
}
/* ------------------------ Test Suite ------------------------ */
describe('Test for Contact Screen', () => {
let props
let wrapper
useIsFocused.mockImplementation(() => true)
beforeEach(async () => {
jest.useRealTimers()
props = createTestProps({})
console.error = jest.fn()
wrapper = mount(
<MockedProvider mocks={mocks} addTypename={false}>
<ContactScreen {...props} />
</MockedProvider>
)
// Wait for sometime for add contact mutation to execute
await new Promise((resolve) => setTimeout(resolve, 1000))
wrapper.update()
})
afterEach(() => {
addFriendMutation = false
addContactsMutation = false
sendInviteMutation = false
wrapper.unmount()
})
test('[T-1] Snapshot and Unit tests', () => {
expect(wrapper).toMatchSnapshot()
expect(wrapper.find(Header)).toHaveLength(1)
expect(wrapper.find(MediumButton)).toHaveLength(1)
expect(wrapper.find(FlatList)).toHaveLength(3)
expect(wrapper.find(ClickableText)).toHaveLength(3)
expect(wrapper.find(Modal)).toHaveLength(1)
})
test('[T-2] Test for AddContacts Mutation', async () => {
expect(addContactsMutation).toBeTruthy()
})
test('[T-3] Does not select friend if Add not pressed', async () => {
// Find the continue button and press on it
const continueButton = wrapper.find(LargeButton).at(0)
continueButton.props().onPress()
await new Promise((resolve) => setTimeout(resolve, 0))
// Check if addFriendMutation is called or not
expect(addFriendMutation).toBeFalsy()
})
test('[T-4] Select Friend if Invite is pressed and Test for SendInvite mutation', async () => {
// Find the user card in invite section and press on 'invite' button
const inviteButton = wrapper.find(Users).at(1).find(TouchableOpacity).at(0)
inviteButton.props().onPress()
wrapper.update()
// Find the continue button and click on it to trigger the send invite mutation
const continueButton = wrapper.find(LargeButton).at(0)
continueButton.props().onPress()
// Wait for sometime for mutation to execute
await new Promise((resolve) => setTimeout(resolve, 1000))
expect(sendInviteMutation).toBeTruthy()
})
test('[T-5] Test for Select All', async () => {
// Find the invite all button of Invite via email
const inviteAllButton = wrapper.find(ClickableText).at(1)
inviteAllButton.props().onPress()
wrapper.update()
// Click on the continue button to send the request to all the friends on newzera
wrapper.find(Modal).find(MediumButton).at(0).props().onPress()
wrapper.update()
// Click on the continue button to trigger the mutation
const continueButton = wrapper.find(LargeButton).at(0)
continueButton.props().onPress()
// Wait for mutation to execute
await new Promise((resolve) => setTimeout(resolve, 1000))
expect(sendInviteMutation).toBeTruthy()
})
test('[T-6] Test for Add Friend mutation', async () => {
// Find the user card in friends on newzera section and click on "Add"
const addButton = wrapper.find(Users).at(0).find(TouchableOpacity).at(0)
addButton.props().onPress()
wrapper.update()
// Find the continue button and click on it
const continueButton = wrapper.find(LargeButton).at(0)
continueButton.props().onPress()
// Wait for mutation to execute
await new Promise((resolve) => setTimeout(resolve, 1000))
expect(addFriendMutation).toBeTruthy()
})
test('[T-7] Test for Add All modal', async () => {
// Find the 'Add All' text and click on it
wrapper.find(ClickableText).at(0).props().onPress()
wrapper.update()
// Snapshot when modal is open!
expect(wrapper).toMatchSnapshot()
// Click on the backdrop to close the modal
wrapper.find(Modal).at(0).props().onBackdropPress()
wrapper.update()
// Snapshot when modal is closed!
expect(wrapper).toMatchSnapshot()
})
test('[T-8] Test for navigation to Welcome Screen', async () => {
// Find the header and click on skip
wrapper.find(Header).at(0).props().onPressRight()
// Check if we are navigating to Welcome Signup screen
expect(props.navigation.navigate).toHaveBeenCalledWith('WelcomeSignUp')
})
test('[T-9] Test for navigation to Follow Content Screen', async () => {
// Find the header and click on back button
wrapper.find(Header).at(0).props().onPressBack()
// Check if we are navigating to Follow content screen
expect(props.navigation.goBack).toHaveBeenCalledTimes(1)
})
test('[T-10] Test for Add All modal close button', async () => {
// Find the 'Add all' text and click on it
wrapper.find(ClickableText).at(0).props().onPress()
wrapper.update()
// Snapshot when modal is open!
expect(wrapper).toMatchSnapshot()
// Close the modal when you click on the cross button
wrapper.find(Modal).find(TouchableOpacity).at(0).props().onPress()
wrapper.update()
// Snapshot when modal is closed!
expect(wrapper).toMatchSnapshot()
})
test('[T-11] Test for button toggle', async () => {
/* ----------- Toggle check for friends on newzera ----------- */
wrapper.find(Users).at(0).find(TouchableOpacity).at(0).props().onPress()
wrapper.update()
// User has been selected
expect(wrapper).toMatchSnapshot()
wrapper.find(Users).at(0).find(TouchableOpacity).at(0).props().onPress()
wrapper.update()
// User has been unselected
expect(wrapper).toMatchSnapshot()
/* ----------- Toggle check for friends with email ----------- */
wrapper.find(Users).at(1).find(TouchableOpacity).at(0).props().onPress()
wrapper.update()
// User has been selected
expect(wrapper).toMatchSnapshot()
wrapper.find(Users).at(1).find(TouchableOpacity).at(0).props().onPress()
wrapper.update()
// User has been unselected
expect(wrapper).toMatchSnapshot()
/* ----------- Toggle check for friends with contact number only ----------- */
wrapper.find(Users).at(3).find(TouchableOpacity).at(0).props().onPress()
wrapper.update()
// User has been selected
expect(wrapper).toMatchSnapshot()
wrapper.find(Users).at(3).find(TouchableOpacity).at(0).props().onPress()
wrapper.update()
// User has been unselected
expect(wrapper).toMatchSnapshot()
})
test('[T-12] Test for Select All friends with contact number only', async () => {
// Find the "Invite all" text in Invite via email and click on it
const inviteAllButton = wrapper.find(ClickableText).at(2)
inviteAllButton.props().onPress()
wrapper.update()
// Click on the continue button to send the request to all the friends on newzera
wrapper.find(Modal).find(MediumButton).at(0).props().onPress()
wrapper.update()
// Click on the continue button to trigger the mutation
const continueButton = wrapper.find(LargeButton).at(0)
continueButton.props().onPress()
// Wait till the mutation executes
await new Promise((resolve) => setTimeout(resolve, 1000))
expect(sendInviteMutation).toBeTruthy()
})
test('[T-13] Test for Add Friend mutation with all friends selected', async () => {
// Find the 'Add all' text and click on it
wrapper.find(ClickableText).at(0).props().onPress()
wrapper.update()
// Click on the continue button to send the request to all the friends on newzera
wrapper.find(Modal).find(MediumButton).at(0).props().onPress()
wrapper.update()
// Click on the continue button to trigger the mutation
const continueButton = wrapper.find(LargeButton).at(0)
continueButton.props().onPress()
// Wait till the mutation executes
await new Promise((resolve) => setTimeout(resolve, 1000))
expect(addFriendMutation).toBeTruthy()
})
test('Test when Async Storage fails', async () => {
const error = new Error('Async Error')
useIsFocused.mockImplementation(() => true)
AsyncStorage.setItem = jest.fn()
AsyncStorage.setItem.mockImplementation(async () => {
throw error
})
let asyncErrorCalled = false
jest.spyOn(console, 'error').mockImplementation((err) => {
if (err === error) asyncErrorCalled = true
})
wrapper = mount(
<MockedProvider mocks={mocks} addTypename={false}>
<ContactScreen {...props} />
</MockedProvider>
)
await new Promise((resolve) => setTimeout(resolve, 1000))
/**
* No visual feedback is present in the code
* Will be replaced by a visual feedback if any of it is added in the future
*/
expect(asyncErrorCalled).toEqual(true)
})
test('If getting Contact info fails with DENIED error', async () => {
useIsFocused.mockImplementation(() => false)
Contacts.getAll.mockImplementation((cb) => {
cb('denied', null)
})
let deniederrorcalled = false
jest.spyOn(console, 'error').mockImplementation((err) => {
if (err == 'denied') deniederrorcalled = true
})
wrapper = mount(
<MockedProvider mocks={mocks} addTypename={false}>
<ContactScreen {...props} />
</MockedProvider>
)
/**
* No visual feedback is present in the code
* Will be replaced by a visual feedback if any of it is added in the future
*/
expect(deniederrorcalled).toEqual(true)
})
})
describe('Testing for different cases of Contacts Output', () => {
beforeEach(() => {
console.error = jest.fn()
resetImplementations()
})
afterEach(() => {
addFriendMutation = false
addContactsMutation = false
sendInviteMutation = false
})
test('Should log an error if data array has an empty object', async () => {
const contactData = {
data: {
AddContacts: [{}]
}
}
let errorcalled = false
jest.spyOn(console, 'error').mockImplementation((err) => {
if (err.message === 'Invalid Data') errorcalled = true
})
const wrapper = mount(
<MockedProvider mocks={createCustomMock(contactData)} addTypename={false}>
<ContactScreen {...createTestProps()} />
</MockedProvider>
)
await new Promise((resolve) => setTimeout(resolve, 1000))
wrapper.update()
expect(errorcalled).toBeTruthy()
})
test('Should log an error if data array does not have Add contact field', async () => {
const contactData = {
data: {}
}
let errorcalled = false
jest.spyOn(console, 'error').mockImplementation((err) => {
if (err === 'Could not add contacts!') errorcalled = true
})
const wrapper = mount(
<MockedProvider mocks={createCustomMock(contactData)} addTypename={false}>
<ContactScreen {...createTestProps()} />
</MockedProvider>
)
await new Promise((resolve) => setTimeout(resolve, 1000))
wrapper.update()
expect(errorcalled).toBeTruthy()
})
test('Should log an error if Add contacts mutation results in error', async () => {
const contactData = {
errors: [new GraphQLError('Error!')]
}
let errorcalled = false
jest.spyOn(console, 'error').mockImplementation((err) => {
if (err === 'Error!') errorcalled = true
})
const wrapper = mount(
<MockedProvider mocks={createCustomMock(contactData)} addTypename={false}>
<ContactScreen {...createTestProps()} />
</MockedProvider>
)
await new Promise((resolve) => setTimeout(resolve, 1000))
wrapper.update()
expect(errorcalled).toBeTruthy()
})
test('Should log an error if data array has an empty object', async () => {
const contactData = {
data: {
AddContacts: [
{
name: 'Carl Jung',
email: 'test@example.com',
contactNumber: '1234',
userId: '1',
contactId: '123',
existingUserId: '001'
}
]
}
}
const wrapper = mount(
<MockedProvider mocks={createCustomMock(contactData)} addTypename={false}>
<ContactScreen {...createTestProps()} />
</MockedProvider>
)
await new Promise((resolve) => setTimeout(resolve, 1000))
wrapper.update()
})
test('User list should be empty when no matching contacts are there ', async () => {
Contacts.getContactsByPhoneNumber.mockImplementation((number, cb) => cb(null, []))
Contacts.getContactsByEmailAddress.mockImplementation((number, cb) => cb(null, []))
const wrapper = mount(
<MockedProvider mocks={mocks} addTypename={false}>
<ContactScreen {...createTestProps()} />
</MockedProvider>
)
await new Promise((resolve) => setTimeout(resolve, 2000))
wrapper.update()
// Find the user card in friends on newzera section and click on "Add"
// Find the continue button and click on it
expect(wrapper.find(Users)).toHaveLength(0)
const continueButton = wrapper.find(LargeButton).at(0)
continueButton.props().onPress()
await new Promise((resolve) => setTimeout(resolve, 0))
// Wait for mutation to execute
wrapper.update()
expect(addFriendMutation).toBeFalsy()
})
test('When Platform select returns false', async () => {
const PlatformSelect = jest.spyOn(Platform, 'select').mockImplementation(() => false)
const wrapper = mount(
<MockedProvider mocks={mocks} addTypename={false}>
<ContactScreen {...createTestProps()} />
</MockedProvider>
)
await new Promise((resolve) => setTimeout(resolve, 2000))
wrapper.update()
expect(wrapper).toMatchSnapshot()
})
})Editor is loading...