Skip to content

Commit

Permalink
Detox e2e tests
Browse files Browse the repository at this point in the history
Setup Detox
Added documentation for detox
Added testIds
Added setup tests for Launch Screen, Home Screen, Conversation Screen
Added helper utils for tests
  • Loading branch information
Alex Risch authored and Alex Risch committed Dec 15, 2023
1 parent 061baa8 commit 69f1289
Show file tree
Hide file tree
Showing 17 changed files with 5,073 additions and 476 deletions.
83 changes: 83 additions & 0 deletions example/.detoxrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/** @type {Detox.DetoxConfig} */
module.exports = {
testRunner: {
args: {
'$0': 'jest',
config: 'e2e/jest.config.js'
},
jest: {
setupTimeout: 120000
}
},
apps: {
'ios.debug': {
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/xmtpreactnativesdkexample.app',
build: 'xcodebuild -workspace ios/xmtpreactnativesdkexample.xcworkspace -scheme xmtpreactnativesdkexample -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
},
'ios.release': {
type: 'ios.app',
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/YOUR_APP.app',
build: 'xcodebuild -workspace ios/YOUR_APP.xcworkspace -scheme YOUR_APP -configuration Release -sdk iphonesimulator -derivedDataPath ios/build'
},
'android.debug': {
type: 'android.apk',
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
reversePorts: [
8081
]
},
'android.release': {
type: 'android.apk',
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
build: 'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release'
}
},
devices: {
simulator: {
type: 'ios.simulator',
device: {
type: 'iPhone 15'
}
},
attached: {
type: 'android.attached',
device: {
adbName: '.*'
}
},
emulator: {
type: 'android.emulator',
device: {
avdName: 'Pixel_3a_API_34_extension_level_7_arm64-v8a'
}
}
},
configurations: {
'ios.sim.debug': {
device: 'simulator',
app: 'ios.debug'
},
'ios.sim.release': {
device: 'simulator',
app: 'ios.release'
},
'android.att.debug': {
device: 'attached',
app: 'android.debug'
},
'android.att.release': {
device: 'attached',
app: 'android.release'
},
'android.emu.debug': {
device: 'emulator',
app: 'android.debug'
},
'android.emu.release': {
device: 'emulator',
app: 'android.release'
}
}
};
1 change: 1 addition & 0 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export default function App() {
onPress={() => navigation.navigate('conversationCreate')}
title="New"
color={Platform.OS === 'ios' ? '#fff' : 'rgb(49 0 110)'}
testID="new-conversation-button"
/>
),
})}
Expand Down
26 changes: 25 additions & 1 deletion example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,28 @@ Running tests locally is useful when updating GitHub actions, or locally testing
5. You can stop the XMTP server with the following command:
```bash
docker-compose -p xmtp -f dev/local/docker-compose.yml down
```
```

## Run e2e tests for example app
Running e2e tests when updating example app with Detox

1. Setup [Detox Prerequisites](https://wix.github.io/Detox/docs/introduction/environment-setup#detox-prerequisites)

2. Update example/.detoxrc.js to match device configs - [More information on device config and debugging issues](https://wix.github.io/Detox/docs/introduction/project-setup#step-3-device-configs)

3. Build the app for testing:
```bash
detox build --configuration ios.sim.debug
```
or
```bash
detox build --configuration android.emu.debug
```
4. Run the tests:
```bash
detox test --configuration ios.sim.debug
```
or
```bash
detox test --configuration android.emu.debug
```
15 changes: 15 additions & 0 deletions example/e2e/conversation-create-screen.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { device } from 'detox'

import { createConversation } from './utils/createConversation'
import { generateDevWallet } from './utils/generateDevWallet'

describe('Conversation Create Screen Tests', () => {
beforeAll(async () => {
await device.launchApp({ newInstance: true })
await generateDevWallet()
})

it('Create Conversation', async () => {
await createConversation()
})
})
17 changes: 17 additions & 0 deletions example/e2e/conversation-screen.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { device } from 'detox'

import { createConversation } from './utils/createConversation'
import { generateDevWallet } from './utils/generateDevWallet'
import { sendMessage } from './utils/sendMessage'

describe('Conversation Screen Tests', () => {
beforeAll(async () => {
await device.launchApp({ newInstance: true })
await generateDevWallet()
await createConversation()
})

it('Send Message in Conversation', async () => {
await sendMessage('Hello World!')
})
})
16 changes: 16 additions & 0 deletions example/e2e/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/** @type {import('@jest/types').Config.InitialOptions} */
const { defaults: tsjPreset } = require('ts-jest/presets')

module.exports = {
...tsjPreset,
preset: 'react-native',
rootDir: '..',
testMatch: ['<rootDir>/e2e/**/*.test.ts'],
testTimeout: 120000,
maxWorkers: 1,
globalSetup: 'detox/runners/jest/globalSetup',
globalTeardown: 'detox/runners/jest/globalTeardown',
reporters: ['detox/runners/jest/reporter'],
testEnvironment: 'detox/runners/jest/testEnvironment',
verbose: true,
};
39 changes: 39 additions & 0 deletions example/e2e/launch-screen.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { device, expect } from 'detox'

import { generateDevWallet } from './utils/generateDevWallet'

describe('Launch Screen Tests', () => {
beforeAll(async () => {
await device.launchApp({ newInstance: true })
})

beforeEach(async () => {
await device.reloadReactNative()
})

it('Tests Button', async () => {
await expect(element(by.id('run-tests-button'))).toBeVisible()
await element(by.id('run-tests-button')).tap()
await waitFor(element(by.id('test-screen')))
.toBeVisible()
.withTimeout(15000)
})

it('Generate Dev Button', async () => {
await generateDevWallet()
})

it('Use Saved Wallet Dev Button', async () => {
await expect(element(by.id('saved-dev-button'))).toBeVisible()
await element(by.id('saved-dev-button')).tap()
await waitFor(element(by.id('home-screen')))
.toBeVisible()
.withTimeout(15000)
})

it('Clear Saved Wallet Dev Button', async () => {
await expect(element(by.id('saved-clear-button'))).toBeVisible()
await element(by.id('saved-clear-button')).tap()
await expect(element(by.id('saved-dev-button'))).not.toBeVisible()
})
})
15 changes: 15 additions & 0 deletions example/e2e/utils/createConversation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { element, waitFor } from 'detox'

export const createConversation = async () => {
await waitFor(element(by.id('home-screen')))
.toBeVisible()
.withTimeout(15000)
await element(by.id('new-conversation-button')).tap()
await element(by.id('to-address-input')).typeText(
'0xc93C111dcb2Df6Bb25a3F9035D5cd47bDc0381d0'
)
await element(by.id('start-conversation-button')).tap()
await waitFor(element(by.id('conversation-screen')))
.toBeVisible()
.withTimeout(15000)
}
9 changes: 9 additions & 0 deletions example/e2e/utils/generateDevWallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { expect } from 'detox'

export const generateDevWallet = async () => {
await expect(element(by.id('generated-dev-button'))).toBeVisible()
await element(by.id('generated-dev-button')).tap()
await waitFor(element(by.id('home-screen')))
.toBeVisible()
.withTimeout(15000)
}
13 changes: 13 additions & 0 deletions example/e2e/utils/sendMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { element } from 'detox'

export const sendMessage = async (message: string) => {
await waitFor(element(by.id('conversation-screen')))
.toBeVisible()
.withTimeout(15000)
await element(by.id('message-input')).typeText(message)
await element(by.id('send-message-button')).tap()

await waitFor(element(by.id(/^conversation-message-.*/)))
.toBeVisible()
.withTimeout(15000)
}
Loading

0 comments on commit 69f1289

Please sign in to comment.