diff --git a/android/app/build.gradle b/android/app/build.gradle index 3dbad6f..33036f0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -113,7 +113,9 @@ android { } dependencies { - androidTestImplementation('com.wix:detox:+') + androidTestImplementation('com.wix:detox:+'){ + exclude module: "protobuf-lite" + } implementation 'androidx.appcompat:appcompat:1.1.0' // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") diff --git a/e2e/TestIds.ts b/e2e/TestIds.ts new file mode 100644 index 0000000..7e5be5d --- /dev/null +++ b/e2e/TestIds.ts @@ -0,0 +1,60 @@ +export enum TestIds { + // Onboarding Wallet Connect + ONBOARDING_CONNECT_WALLET_BUTTON = 'ONBOARDING_CONNECT_WALLET_BUTTON', + ONBOARDING_CONNECT_WALLET_SCREEN = 'ONBOARDING_CONNECT_WALLET_SCREEN', + ONBOARDING_CONNECT_WALLET_CONNECT_OPTION_BUTTON = 'ONBOARDING_CONNECT_WALLET_CONNECT_OPTION_BUTTON', + ONBOARDING_CONNECT_METAMASK_OPTION_BUTTON = 'ONBOARDING_CONNECT_METAMASK_OPTION_BUTTON', + ONBOARDING_CONNECT_COINBASE_OPTION_BUTTON = 'ONBOARDING_CONNECT_COINBASE_OPTION_BUTTON', + ONBOARDING_CONNECT_GUEST_OPTION_BUTTON = 'ONBOARDING_CONNECT_GUEST_OPTION_BUTTON', + + // Conversation List + CONVERSATION_LIST_SCREEN = 'CONVERSATION_LIST_SCREEN', + CONVERSATION_LIST_ITEM = 'CONVERSATION_LIST_ITEM', + CONVERSATION_LIST_ITEM_AVATAR = 'CONVERSATION_LIST_ITEM_AVATAR', + CONVERSATION_LIST_ITEM_TITLE = 'CONVERSATION_LIST_ITEM_TITLE', + CONVERSATION_LIST_ITEM_TEXT = 'CONVERSATION_LIST_ITEM_TEXT', + CONVERSATION_LIST_ITEM_TIME = 'CONVERSATION_LIST_ITEM_TIME', + CONVERSATION_LIST_ALL_MESSAGES_TITLE = 'CONVERSATION_LIST_ALL_MESSAGES_TITLE', + CONVERSATION_LIST_REQUESTS_TITLE = 'CONVERSATION_LIST_REQUESTS_TITLE', + CONVERSATION_LIST_EMPTY_STATE = 'CONVERSATION_LIST_EMPTY_STATE', + CONVERSATION_LIST_ALL_MESSAGES_BUTTON = 'CONVERSATION_LIST_ALL_MESSAGES_BUTTON', + CONVERSATION_LIST_REQUESTS_BUTTON = 'CONVERSATION_LIST_REQUESTS_BUTTON', + CONVERSATION_LIST_PROFILE_BUTTON = 'CONVERSATION_LIST_PROFILE_BUTTON', + CONVERSATION_LIST_DISCOVER_BUTTON = 'CONVERSATION_LIST_DISCOVER_BUTTON', + CONVERSATION_LIST_NEW_BUTTON = 'CONVERSATION_LIST_NEW_BUTTON', + + // Conversation + CONVERSATION_SCREEN = 'CONVERSATION_SCREEN', + CONVERSATION_INPUT = 'CONVERSATION_INPUT', + CONVERSATION_MESSAGE = 'CONVERSATION_MESSAGE', + CONVERSATION_SEND_BUTTON = 'CONVERSATION_SEND_BUTTON', + CONVERSATION_CAMERA_BUTTON = 'CONVERSATION_CAMERA_BUTTON', + CONVERSATION_GALLERY_BUTTON = 'CONVERSATION_GALLERY_BUTTON', + CONVERSATION_PROFILE_BUTTON = 'CONVERSATION_PROFILE_BUTTON', + CONVERSATION_HEADER_TITLE = 'CONVERSATION_HEADER_TITLE', + + // Group + GROUP_SCREEN = 'GROUP_SCREEN', + GROUP_INPUT = 'GROUP_INPUT', + GROUP_MESSAGE = 'GROUP_MESSAGE', + GROUP_SEND_BUTTON = 'GROUP_SEND_BUTTON', + GROUP_CAMERA_BUTTON = 'GROUP_CAMERA_BUTTON', + GROUP_GALLERY_BUTTON = 'GROUP_GALLERY_BUTTON', + GROUP_PROFILE_BUTTON = 'GROUP_PROFILE_BUTTON', + GROUP_HEADER_TITLE = 'GROUP_HEADER_TITLE', + + // Search + SEARCH_SCREEN = 'SEARCH_SCREEN', + SEARCH_INPUT = 'SEARCH_INPUT', + SEARCH_RESULT = 'SEARCH_RESULT', + SEARCH_RECENT_RESULT = 'RECENT_RESULT', + SEARCH_CONTACTS_RESULT = 'CONTACTS_RESULT', + SEARCH_START_BUTTON = 'SEARCH_START_BUTTON', + SEARCH_PARTICIPANTS_LIST_PILL = 'SEARCH_PARTICIPANTS_LIST_PILL', + + // Account + ACCOUNT_SCREEN = 'ACCOUNT_SCREEN', + + // Discover + DISCOVER_SCREEN = 'DISCOVER_SCREEN', +} diff --git a/e2e/jest.config.js b/e2e/jest.config.js index 4f98020..b0ae98a 100644 --- a/e2e/jest.config.js +++ b/e2e/jest.config.js @@ -1,7 +1,7 @@ /** @type {import('@jest/types').Config.InitialOptions} */ module.exports = { rootDir: '..', - testMatch: ['/e2e/**/*.test.js'], + testMatch: ['/e2e/**/*.test.ts'], testTimeout: 120000, maxWorkers: 1, globalSetup: 'detox/runners/jest/globalSetup', diff --git a/e2e/starter.test.js b/e2e/starter.test.js deleted file mode 100644 index e415cff..0000000 --- a/e2e/starter.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import {by, device, element} from 'detox'; - -describe('Example', () => { - beforeAll(async () => { - await device.launchApp(); - }); - - beforeEach(async () => { - await device.reloadReactNative(); - }); - - it('should have welcome screen', async () => { - await expect(element(by.id('welcome-text-1'))).toBeVisible(); - }); -}); diff --git a/e2e/starter.test.ts b/e2e/starter.test.ts new file mode 100644 index 0000000..c96f88a --- /dev/null +++ b/e2e/starter.test.ts @@ -0,0 +1,46 @@ +import {by, device, element, expect} from 'detox'; +import {TestIds} from './TestIds'; + +describe('Example', () => { + beforeAll(async () => { + await device.launchApp(); + }); + + beforeEach(async () => { + await device.reloadReactNative(); + }); + + it('should have welcome screen', async () => { + const address1 = '0x1f07ccCb84F550100a786EAFf7e7179C52b0aC8d'; + // const address2 = '0x62BdD7864695d8B4c760CD1ea5635cD23A84d513'; + await expect( + element(by.id(TestIds.ONBOARDING_CONNECT_WALLET_SCREEN)), + ).toBeVisible(); + await expect( + element(by.id(TestIds.ONBOARDING_CONNECT_WALLET_BUTTON)), + ).toBeVisible(); + await element(by.id(TestIds.ONBOARDING_CONNECT_WALLET_BUTTON)).tap(); + await expect( + element(by.id(TestIds.ONBOARDING_CONNECT_GUEST_OPTION_BUTTON)), + ).toBeVisible(); + await element(by.id(TestIds.ONBOARDING_CONNECT_GUEST_OPTION_BUTTON)).tap(); + await waitFor(element(by.id(TestIds.CONVERSATION_LIST_SCREEN))) + .toBeVisible() + .withTimeout(5000); + await expect( + element(by.id(TestIds.CONVERSATION_LIST_NEW_BUTTON)), + ).toBeVisible(); + await element(by.id(TestIds.CONVERSATION_LIST_NEW_BUTTON)).tap(); + await expect(element(by.id(TestIds.SEARCH_SCREEN))).toBeVisible(); + await expect(element(by.id(TestIds.SEARCH_INPUT))).toBeVisible(); + await element(by.id(TestIds.SEARCH_INPUT)).typeText(address1); + await expect( + element(by.id(`${TestIds.SEARCH_RESULT}_${address1}`)), + ).toBeVisible(); + await element(by.id(`${TestIds.SEARCH_RESULT}_${address1}`)).tap(); + await expect(element(by.id(TestIds.SEARCH_START_BUTTON))).toBeVisible(); + await element(by.id(TestIds.SEARCH_START_BUTTON)).tap(); + await expect(element(by.id(TestIds.CONVERSATION_SCREEN))).toBeVisible(); + await expect(element(by.id(TestIds.CONVERSATION_INPUT))).toBeVisible(); + }); +}); diff --git a/src/components/WalletOptionButton.tsx b/src/components/WalletOptionButton.tsx index 78ae2db..cf1e859 100644 --- a/src/components/WalletOptionButton.tsx +++ b/src/components/WalletOptionButton.tsx @@ -8,15 +8,17 @@ interface WalletOptionButtonProps { onPress: () => void; title: string; icon: IconName; + testId: string; } export const WalletOptionButton: FC = ({ onPress, title, icon, + testId, }) => { return ( - + void; size?: 'sm' | 'md' | 'lg'; + testId?: string; } export const Pill: FC = ({ @@ -17,6 +18,7 @@ export const Pill: FC = ({ onPress, rightIconName, size, + testId, }) => { const sizeProps = useMemo(() => { if (size === 'sm') { @@ -48,7 +50,7 @@ export const Pill: FC = ({ }, [size]); return ( - + = ({ @@ -22,10 +23,12 @@ export const Screen: FC = ({ containerStlye, includeTopPadding = true, includeBackground = true, + testId, }) => { const showHeader = left || right || title; return ( { const {navigate, goBack} = useTypedNavigation(); - const {setClient} = useClientContext(); + const {client, setClient} = useClientContext(); const {avatarUrl, addresses, wallets, name} = useData(); const [walletsShown, setWalletsShown] = useState(false); const disconnect = useDisconnect(); @@ -308,6 +309,9 @@ export const AccountSettingsScreen = () => { address={address ?? ''} /> {addresses.map(address => ( diff --git a/src/screens/ConversationListScreen.tsx b/src/screens/ConversationListScreen.tsx index 83f7fba..6cbd5f5 100644 --- a/src/screens/ConversationListScreen.tsx +++ b/src/screens/ConversationListScreen.tsx @@ -11,6 +11,7 @@ import {Drawer} from '../components/common/Drawer'; import {Icon} from '../components/common/Icon'; import {Screen} from '../components/common/Screen'; import {Text} from '../components/common/Text'; +import {TestIds} from '../consts/TestIds'; import {useClient} from '../hooks/useClient'; import {useListMessages} from '../hooks/useListMessages'; import {useTypedNavigation} from '../hooks/useTypedNavigation'; @@ -239,7 +240,7 @@ export const ConversationListScreen = () => { return ( <> - + { /> {!showPickerModal && focused && ( { isOpen={showPickerModal} onBackgroundPress={() => setShowPickerModal(false)}> - handleFilterPress('ALL_MESSAGES')}> + handleFilterPress('ALL_MESSAGES')} + testID={TestIds.CONVERSATION_LIST_ALL_MESSAGES_BUTTON}> { )} - handleFilterPress('MESSAGE_REQUESTS')}> + handleFilterPress('MESSAGE_REQUESTS')} + testID={TestIds.CONVERSATION_LIST_REQUESTS_BUTTON}> { return ( <> - + { width={'100%'} flex={1} paddingX={'24px'}> - + {translate('your_interoperable_web3_inbox')} @@ -72,6 +73,7 @@ export const OnboardingConnectWalletScreen = () => { <> @@ -97,6 +99,7 @@ export const OnboardingConnectWalletScreen = () => { }} title={translate('walletconnect')} icon={'walletconnect'} + testId={TestIds.ONBOARDING_CONNECT_WALLET_CONNECT_OPTION_BUTTON} /> { @@ -105,6 +108,7 @@ export const OnboardingConnectWalletScreen = () => { }} title={translate('metamask')} icon={'metamask'} + testId={TestIds.ONBOARDING_CONNECT_METAMASK_OPTION_BUTTON} /> { @@ -113,18 +117,17 @@ export const OnboardingConnectWalletScreen = () => { }} title={translate('coinbase_wallet')} icon={'coinbase-wallet'} + testId={TestIds.ONBOARDING_CONNECT_COINBASE_OPTION_BUTTON} + /> + { + await connect(localWalletConfig); + setShowModal(false); + }} + title={translate('guest_wallet')} + icon={'wallet'} + testId={TestIds.ONBOARDING_CONNECT_GUEST_OPTION_BUTTON} /> - {__DEV__ && ( - { - await connect(localWalletConfig); - setShowModal(false); - }} - title={translate('guest_wallet')} - icon={'wallet'} - /> - )} -