contacts screen
unknown
plain_text
4 years ago
20 kB
6
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...