From 3cfbf54ae20a83324c271a2e92b23ca4d72f52ce Mon Sep 17 00:00:00 2001 From: Simon Racz Date: Tue, 26 Sep 2017 12:21:45 +0200 Subject: [PATCH 1/4] [Android] label -> contentDescription and test suite fixes --- detox/src/android/expect.js | 2 +- detox/test/e2e/a-sanity.js | 4 ++-- detox/test/e2e/b-matchers.js | 4 ++-- detox/test/package.json | 12 ++++++++++-- detox/test/src/Screens/ActionsScreen.js | 2 +- detox/test/src/Screens/MatchersScreen.js | 4 ++-- detox/test/src/Screens/SanityScreen.js | 4 ++-- detox/test/src/app.js | 2 +- 8 files changed, 21 insertions(+), 13 deletions(-) diff --git a/detox/src/android/expect.js b/detox/src/android/expect.js index 921318c477..5619731fb1 100644 --- a/detox/src/android/expect.js +++ b/detox/src/android/expect.js @@ -340,7 +340,7 @@ function element(matcher) { const by = { accessibilityLabel: (value) => new LabelMatcher(value), - label: (value) => new TextMatcher(value), + label: (value) => new LabelMatcher(value), id: (value) => new IdMatcher(value), type: (value) => new TypeMatcher(value), traits: (value) => new TraitsMatcher(value), diff --git a/detox/test/e2e/a-sanity.js b/detox/test/e2e/a-sanity.js index 460a5f06dc..3117b5d863 100644 --- a/detox/test/e2e/a-sanity.js +++ b/detox/test/e2e/a-sanity.js @@ -15,11 +15,11 @@ describe('Sanity', () => { it('should show hello screen after tap', async () => { await element(by.label('Say Hello')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('should show world screen after tap', async () => { await element(by.label('Say World')).tap(); - await expect(element(by.label('World!!!'))).toBeVisible(); + await expect(element(by.text('World!!!'))).toBeVisible(); }); }); diff --git a/detox/test/e2e/b-matchers.js b/detox/test/e2e/b-matchers.js index 09ecff81a1..dafac3f709 100644 --- a/detox/test/e2e/b-matchers.js +++ b/detox/test/e2e/b-matchers.js @@ -6,12 +6,12 @@ describe('Matchers', () => { it('should match elements by (accesibility) label', async () => { await element(by.label('Label')).tap(); - await expect(element(by.label('Label Working!!!'))).toBeVisible(); + await expect(element(by.text('Label Working!!!'))).toBeVisible(); }); it('should match elements by (accesibility) id', async () => { await element(by.id('UniqueId345')).tap(); - await expect(element(by.label('ID Working!!!'))).toBeVisible(); + await expect(element(by.text('ID Working!!!'))).toBeVisible(); }); it('should match elements by type (native class)', async () => { diff --git a/detox/test/package.json b/detox/test/package.json index 0154aa92a0..452682be15 100644 --- a/detox/test/package.json +++ b/detox/test/package.json @@ -49,13 +49,21 @@ "binaryPath": "android/app/build/outputs/apk/app-debug.apk", "build": "pushd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && popd", "type": "android.emulator", - "name": "Nexus_5X_API_24_-_GPlay" + "name": "Nexus_5X_API_24_-_GPlay", + "session": { + "server": "ws://localhost:8099", + "sessionId": "test" + } }, "android.emu.release": { "binaryPath": "android/app/build/outputs/apk/app-release.apk", "build": "pushd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && popd", "type": "android.emulator", - "name": "Nexus_5X_API_24_-_GPlay" + "name": "Nexus_5X_API_24_-_GPlay", + "session": { + "server": "ws://localhost:8099", + "sessionId": "test" + } } } } diff --git a/detox/test/src/Screens/ActionsScreen.js b/detox/test/src/Screens/ActionsScreen.js index 0d534e4c50..eabab2516c 100644 --- a/detox/test/src/Screens/ActionsScreen.js +++ b/detox/test/src/Screens/ActionsScreen.js @@ -29,7 +29,7 @@ export default class ActionsScreen extends Component { - Tap Me + Tap Me - Label + Label - ID + ID diff --git a/detox/test/src/Screens/SanityScreen.js b/detox/test/src/Screens/SanityScreen.js index 494a36d71d..2baabeb6f8 100644 --- a/detox/test/src/Screens/SanityScreen.js +++ b/detox/test/src/Screens/SanityScreen.js @@ -18,7 +18,7 @@ export default class SanityScreen extends Component { renderTestButton(label, onPress) { return ( - {label} + {label} ) } @@ -27,7 +27,7 @@ export default class SanityScreen extends Component { if (this.state.greeting) return this.renderAfterButton(); return ( - + Welcome {this.renderTestButton('Say Hello', this.onButtonPress.bind(this, 'Hello'))} diff --git a/detox/test/src/app.js b/detox/test/src/app.js index fa000aca38..8d1b89879c 100644 --- a/detox/test/src/app.js +++ b/detox/test/src/app.js @@ -24,7 +24,7 @@ class example extends Component { { this.setState({screen: component}); }}> - {title} + {title} ); } From 5b130fe700bde7e9c366b43214fcc85f0436524d Mon Sep 17 00:00:00 2001 From: Simon Racz Date: Tue, 26 Sep 2017 13:57:16 +0200 Subject: [PATCH 2/4] [Android] label -> text rewrite finished where needed --- .../android/app/src/main/AndroidManifest.xml | 1 + detox/test/e2e/c-actions.js | 16 +++++++------- detox/test/e2e/f-device.js | 12 +++++------ detox/test/e2e/g-stress-tests.js | 10 ++++----- detox/test/e2e/h-stress-root.js | 4 ++-- detox/test/e2e/i-stress-timeouts.js | 14 ++++++------- detox/test/e2e/k-user-notifications.js | 8 +++---- detox/test/e2e/m-network.js | 21 ++++++++++--------- detox/test/e2e/n-deep-links.js | 6 +++--- detox/test/src/Screens/ActionsScreen.js | 20 +++++++++--------- detox/test/src/Screens/AssertionsScreen.js | 2 +- detox/test/src/Screens/NetworkScreen.js | 5 +++-- detox/test/src/Screens/Orientation.js | 2 +- detox/test/src/Screens/StressScreen.js | 4 ++-- detox/test/src/Screens/SwitchRootScreen.js | 4 ++-- detox/test/src/Screens/TimeoutsScreen.js | 12 +++++------ detox/test/src/Screens/WaitForScreen.js | 16 +++++++------- 17 files changed, 80 insertions(+), 77 deletions(-) diff --git a/detox/test/android/app/src/main/AndroidManifest.xml b/detox/test/android/app/src/main/AndroidManifest.xml index d9ae56a063..999ac19ad5 100644 --- a/detox/test/android/app/src/main/AndroidManifest.xml +++ b/detox/test/android/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ + { it('should tap on an element', async () => { await element(by.label('Tap Me')).tap(); - await expect(element(by.label('Tap Working!!!'))).toBeVisible(); + await expect(element(by.text('Tap Working!!!'))).toBeVisible(); }); it('should long press on an element', async () => { await element(by.label('Tap Me')).longPress(); - await expect(element(by.label('Long Press Working!!!'))).toBeVisible(); + await expect(element(by.text('Long Press Working!!!'))).toBeVisible(); }); it('should multi tap on an element', async () => { await element(by.id('UniqueId819')).multiTap(3); - await expect(element(by.id('UniqueId819'))).toHaveLabel('Taps: 3'); + await expect(element(by.id('UniqueId819'))).toHaveText('Taps: 3'); }); it('should tap on an element at point', async () => { await element(by.id('View7990')).tapAtPoint({x:180, y:140}); - await expect(element(by.id('UniqueId819'))).toHaveLabel('Taps: 1'); + await expect(element(by.id('UniqueId819'))).toHaveText('Taps: 1'); }); // Backspace is supported by using "\b" in the string. Return key is supported with "\n" it('should type in an element', async () => { await element(by.id('UniqueId937')).tap(); await element(by.id('UniqueId937')).typeText('passcode'); - await expect(element(by.label('Type Working!!!'))).toBeVisible(); + await expect(element(by.text('Type Working!!!'))).toBeVisible(); }); it('should clear text in an element', async () => { await element(by.id('UniqueId005')).tap(); await element(by.id('UniqueId005')).clearText(); - await expect(element(by.label('Clear Working!!!'))).toBeVisible(); + await expect(element(by.text('Clear Working!!!'))).toBeVisible(); }); it('should replace text in an element', async () => { await element(by.id('UniqueId006')).tap(); await element(by.id('UniqueId006')).replaceText('replaced_text'); - await expect(element(by.label('Replace Working!!!'))).toBeVisible(); + await expect(element(by.text('Replace Working!!!'))).toBeVisible(); }); // directions: 'up'/'down'/'left'/'right' @@ -78,7 +78,7 @@ describe('Actions', () => { // directions: 'up'/'down'/'left'/'right', speed: 'fast'/'slow' xit('should swipe down until pull to reload is triggered', async () => { await element(by.id('ScrollView799')).swipe('down', 'slow'); - await expect(element(by.label('PullToReload Working!!!'))).toBeVisible(); + await expect(element(by.text('PullToReload Working!!!'))).toBeVisible(); }); it('should wait for long timeout', async () => { diff --git a/detox/test/e2e/f-device.js b/detox/test/e2e/f-device.js index 71be8c9aba..8389bf27ef 100644 --- a/detox/test/e2e/f-device.js +++ b/detox/test/e2e/f-device.js @@ -3,21 +3,21 @@ describe('Device', () => { await device.reloadReactNative(); await element(by.label('Sanity')).tap(); await element(by.label('Say Hello')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('relaunchApp - should tap successfully', async () => { await device.relaunchApp(); await element(by.label('Sanity')).tap(); await element(by.label('Say Hello')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('relaunchApp({delete: true}) - should tap successfully', async () => { await device.relaunchApp({delete: true}); await element(by.label('Sanity')).tap(); await element(by.label('Say Hello')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('uninstall() + install() + relaunch() - should tap successfully', async () => { @@ -26,7 +26,7 @@ describe('Device', () => { await device.relaunchApp(); await element(by.label('Sanity')).tap(); await element(by.label('Say Hello')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('launchApp({newInstance: true}) + sendToHome() + launchApp() - should bring up previous instance', async () => { @@ -36,7 +36,7 @@ describe('Device', () => { await device.sendToHome(); await device.launchApp(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('resetContentAndSettings() + install() + relaunch() - should tap successfully', async () => { @@ -45,7 +45,7 @@ describe('Device', () => { await device.launchApp({ newInstance: true }); await element(by.label('Sanity')).tap(); await element(by.label('Say Hello')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); describe('device orientation', () => { diff --git a/detox/test/e2e/g-stress-tests.js b/detox/test/e2e/g-stress-tests.js index adf905a2b6..b6362d6961 100644 --- a/detox/test/e2e/g-stress-tests.js +++ b/detox/test/e2e/g-stress-tests.js @@ -10,31 +10,31 @@ describe('StressTests', () => { it('should handle tap during busy bridge (one way)', async () => { await element(by.label('Bridge OneWay Stress')).tap(); await element(by.label('Next')).tap(); - await expect(element(by.label('BridgeOneWay'))).toBeVisible(); + await expect(element(by.text('BridgeOneWay'))).toBeVisible(); }); it('should handle tap during busy bridge (two way)', async () => { await element(by.label('Bridge TwoWay Stress')).tap(); await element(by.label('Next')).tap(); - await expect(element(by.label('BridgeTwoWay'))).toBeVisible(); + await expect(element(by.text('BridgeTwoWay'))).toBeVisible(); }); it('should handle tap during busy bridge (setState)', async () => { await element(by.label('Bridge setState Stress')).tap(); await element(by.label('Next')).tap(); - await expect(element(by.label('BridgeSetState'))).toBeVisible(); + await expect(element(by.text('BridgeSetState'))).toBeVisible(); }); it('should handle tap during busy JS event loop', async () => { await element(by.label('EventLoop Stress')).tap(); await element(by.label('Next')).tap(); - await expect(element(by.label('EventLoop'))).toBeVisible(); + await expect(element(by.text('EventLoop'))).toBeVisible(); }); it('should handle consecutive taps', async () => { const TAP_COUNT = 20; for (let i = 1; i <= TAP_COUNT; i++) { - await element(by.label('Consecutive Stress ' + i)).tap(); + await element(by.text('Consecutive Stress ' + i)).tap(); } }); }); diff --git a/detox/test/e2e/h-stress-root.js b/detox/test/e2e/h-stress-root.js index c5a64f2110..d7e82382ba 100644 --- a/detox/test/e2e/h-stress-root.js +++ b/detox/test/e2e/h-stress-root.js @@ -13,11 +13,11 @@ describe('StressRoot', () => { it('should switch root view controller from RN to native', async () => { await element(by.label('Switch to a new native root')).tap(); - await expect(element(by.label('this is a new native root'))).toBeVisible(); + await expect(element(by.text('this is a new native root'))).toBeVisible(); }); it(':ios: should switch root view controller from RN to RN', async () => { await element(by.label('Switch to multiple react roots')).tap(); - await expect(element(by.label('Choose a test'))).toBeVisible(); + await expect(element(by.text('Choose a test'))).toBeVisible(); }); }); diff --git a/detox/test/e2e/i-stress-timeouts.js b/detox/test/e2e/i-stress-timeouts.js index 3ae2ec6bd8..60f2e8d9b5 100644 --- a/detox/test/e2e/i-stress-timeouts.js +++ b/detox/test/e2e/i-stress-timeouts.js @@ -7,33 +7,33 @@ describe('StressTimeouts', () => { await element(by.label('Timeouts')).tap(); }); - it('should handle a short timeout', async () => { + it(':ios: should handle a short timeout', async () => { await element(by.id('TimeoutShort')).tap(); - await expect(element(by.label('Short Timeout Working!!!'))).toBeVisible(); + await expect(element(by.text('Short Timeout Working!!!'))).toBeVisible(); }); it('should handle zero timeout', async () => { await element(by.id('TimeoutZero')).tap(); - await expect(element(by.label('Zero Timeout Working!!!'))).toBeVisible(); + await expect(element(by.text('Zero Timeout Working!!!'))).toBeVisible(); }); it('should ignore a short timeout', async () => { await element(by.id('TimeoutIgnoreShort')).tap(); - await expect(element(by.label('Short Timeout Ignored!!!'))).toBeVisible(); + await expect(element(by.text('Short Timeout Ignored!!!'))).toBeVisible(); }); it('should ignore a long timeout', async () => { await element(by.id('TimeoutIgnoreLong')).tap(); - await expect(element(by.label('Long Timeout Ignored!!!'))).toBeVisible(); + await expect(element(by.text('Long Timeout Ignored!!!'))).toBeVisible(); }); it('should handle setImmediate', async () => { await element(by.id('Immediate')).tap(); - await expect(element(by.label('Immediate Working!!!'))).toBeVisible(); + await expect(element(by.text('Immediate Working!!!'))).toBeVisible(); }); it('should ignore setInterval', async () => { await element(by.id('IntervalIgnore')).tap(); - await expect(element(by.label('Interval Ignored!!!'))).toBeVisible(); + await expect(element(by.text('Interval Ignored!!!'))).toBeVisible(); }); }); diff --git a/detox/test/e2e/k-user-notifications.js b/detox/test/e2e/k-user-notifications.js index 37c652bf35..11c6e417d5 100644 --- a/detox/test/e2e/k-user-notifications.js +++ b/detox/test/e2e/k-user-notifications.js @@ -1,26 +1,26 @@ describe(':ios: User Notifications', () => { it('Init from user notification', async () => { await device.launchApp({newInstance:true, userNotification: userNotificationPushTrigger}); - await expect(element(by.label('From push'))).toBeVisible(); + await expect(element(by.text('From push'))).toBeVisible(); }); it('Background user notification', async () => { await device.launchApp({newInstance:true}); await device.sendToHome(); await device.launchApp({newInstance:false, userNotification: userNotificationCalendarTrigger}); - await expect(element(by.label('From calendar'))).toBeVisible(); + await expect(element(by.text('From calendar'))).toBeVisible(); }); it('Foreground user notifications - local notification from inside the app - async', async () => { await device.launchApp(); await device.sendUserNotification(userNotificationCalendarTrigger); - await expect(element(by.label('From calendar'))).toBeVisible(); + await expect(element(by.text('From calendar'))).toBeVisible(); }); it('Foreground user notifications - local notification from inside the app - promises + callback', (done) => { device.launchApp() .then(() => device.sendUserNotification(userNotificationCalendarTrigger) - .then(() => expect(element(by.label('From calendar'))).toBeVisible())) + .then(() => expect(element(by.text('From calendar'))).toBeVisible())) .then(done); }); }); diff --git a/detox/test/e2e/m-network.js b/detox/test/e2e/m-network.js index ea27afabad..55fe709788 100644 --- a/detox/test/e2e/m-network.js +++ b/detox/test/e2e/m-network.js @@ -18,33 +18,34 @@ describe('Network Synchronization', () => { it('Sync with short network requests - 100ms', async () => { await element(by.id('ShortNetworkRequest')).tap(); - await expect(element(by.label('Short Network Request Working!!!'))).toBeVisible(); + await expect(element(by.text('Short Network Request Working!!!'))).toBeVisible(); }); it('Sync with long network requests - 3000ms', async () => { await element(by.id('LongNetworkRequest')).tap(); - await expect(element(by.label('Long Network Request Working!!!'))).toBeVisible(); + await expect(element(by.text('Long Network Request Working!!!'))).toBeVisible(); }); it('disableSynchronization() should disable sync', async () => { await device.disableSynchronization(); await waitFor(element(by.id('LongNetworkRequest'))).toBeVisible().withTimeout(4000); await element(by.id('LongNetworkRequest')).tap(); - await expect(element(by.label('Long Network Request Working!!!'))).toBeNotVisible(); - await waitFor(element(by.label('Long Network Request Working!!!'))).toBeVisible().withTimeout(4000); - await expect(element(by.label('Long Network Request Working!!!'))).toBeVisible(); + await expect(element(by.text('Long Network Request Working!!!'))).toBeNotVisible(); + await waitFor(element(by.text('Long Network Request Working!!!'))).toBeVisible().withTimeout(4000); + await expect(element(by.text('Long Network Request Working!!!'))).toBeVisible(); await device.enableSynchronization(); }); - it('setURLBlacklist() should disable synchronization for given endpoint', async () => { - await device.setURLBlacklist(['.*localhost.*']); + it(':ios: setURLBlacklist() should disable synchronization for given endpoint', async () => { + const url = device.getPlatform() === 'ios' ? '.*localhost.*' : '*10.0.2.2*'; + await device.setURLBlacklist([url]); await element(by.id('LongNetworkRequest')).tap(); - await expect(element(by.label('Long Network Request Working!!!'))).toBeNotVisible(); - await waitFor(element(by.label('Long Network Request Working!!!'))).toBeVisible().withTimeout(4000); - await expect(element(by.label('Long Network Request Working!!!'))).toBeVisible(); + await expect(element(by.text('Long Network Request Working!!!'))).toBeNotVisible(); + await waitFor(element(by.text('Long Network Request Working!!!'))).toBeVisible().withTimeout(4000); + await expect(element(by.text('Long Network Request Working!!!'))).toBeVisible(); await device.setURLBlacklist([]); }); diff --git a/detox/test/e2e/n-deep-links.js b/detox/test/e2e/n-deep-links.js index a6137be67e..216e217922 100644 --- a/detox/test/e2e/n-deep-links.js +++ b/detox/test/e2e/n-deep-links.js @@ -3,14 +3,14 @@ describe('Deep Links', () => { it('device.launchApp({{newInstance: true, url: url}) should launch app and trigger handling of deep links in app', async () => { const url = 'detoxtesturlscheme://such-string'; await device.launchApp({newInstance: true, url: url}); - await expect(element(by.label(url))).toBeVisible(); + await expect(element(by.text(url))).toBeVisible(); }); it('device.openURL({url: url}) should trigger handling of deep links in app when app is in foreground', async () => { const url = 'detoxtesturlscheme://such-string'; await device.launchApp({newInstance: true}); await device.openURL({url: url}); - await expect(element(by.label(url))).toBeVisible(); + await expect(element(by.text(url))).toBeVisible(); }); it('device.launchApp({url: url}) should trigger handling of deep links in app when app is in background', async () => { @@ -18,6 +18,6 @@ describe('Deep Links', () => { await device.launchApp({newInstance: true}); await device.sendToHome(); await device.launchApp({newInstance: false, url: url}); - await expect(element(by.label(url))).toBeVisible(); + await expect(element(by.text(url))).toBeVisible(); }); }); diff --git a/detox/test/src/Screens/ActionsScreen.js b/detox/test/src/Screens/ActionsScreen.js index eabab2516c..e5d9080e78 100644 --- a/detox/test/src/Screens/ActionsScreen.js +++ b/detox/test/src/Screens/ActionsScreen.js @@ -29,12 +29,12 @@ export default class ActionsScreen extends Component { - Tap Me + Tap Me - Tap Me For Long Timeout + Tap Me For Long Timeout @@ -62,14 +62,14 @@ export default class ActionsScreen extends Component { - Text1 - Text2 - Text3 - Text4 - Text5 - Text6 - Text7 - Text8 + Text1 + Text2 + Text3 + Text4 + Text5 + Text6 + Text7 + Text8 diff --git a/detox/test/src/Screens/AssertionsScreen.js b/detox/test/src/Screens/AssertionsScreen.js index 388eb24ae5..3ba907a51d 100644 --- a/detox/test/src/Screens/AssertionsScreen.js +++ b/detox/test/src/Screens/AssertionsScreen.js @@ -18,7 +18,7 @@ export default class AssertionsScreen extends Component { return ( - I contain some text + I contain some text I am not visible diff --git a/detox/test/src/Screens/NetworkScreen.js b/detox/test/src/Screens/NetworkScreen.js index ae3bf3bd9b..f988f4a6c9 100644 --- a/detox/test/src/Screens/NetworkScreen.js +++ b/detox/test/src/Screens/NetworkScreen.js @@ -6,6 +6,7 @@ import { Platform } from 'react-native'; +// TODO Use 10.0.3.2 for Genymotion const HOST = Platform.OS === 'ios' ? 'localhost': '10.0.2.2'; export default class NetworkScreen extends Component { @@ -23,11 +24,11 @@ export default class NetworkScreen extends Component { - Short Network Request + Short Network Request - Long Network Request + Long Network Request ); diff --git a/detox/test/src/Screens/Orientation.js b/detox/test/src/Screens/Orientation.js index 9d91402679..35f5bba2ba 100644 --- a/detox/test/src/Screens/Orientation.js +++ b/detox/test/src/Screens/Orientation.js @@ -24,7 +24,7 @@ export default class Orientation extends Component { render() { return ( - + {this.state.horizontal ? 'Landscape' : 'Portrait'} diff --git a/detox/test/src/Screens/StressScreen.js b/detox/test/src/Screens/StressScreen.js index 45b4bf5fda..15f0ce9a45 100644 --- a/detox/test/src/Screens/StressScreen.js +++ b/detox/test/src/Screens/StressScreen.js @@ -61,7 +61,7 @@ export default class StressScreen extends Component { renderTestButton(label, onPress) { return ( - {label} + {label} ) } @@ -100,7 +100,7 @@ export default class StressScreen extends Component { return ( - Next + Next ); diff --git a/detox/test/src/Screens/SwitchRootScreen.js b/detox/test/src/Screens/SwitchRootScreen.js index 3ec8cf57ca..00fb03a031 100644 --- a/detox/test/src/Screens/SwitchRootScreen.js +++ b/detox/test/src/Screens/SwitchRootScreen.js @@ -13,10 +13,10 @@ export default class SwitchRootScreen extends Component { return ( NativeModule.switchToNativeRoot()}> - {`Switch to a new native root`} + {`Switch to a new native root`} NativeModule.switchToMultipleReactRoots()}> - {`Switch to multiple react roots`} + {`Switch to multiple react roots`} ); diff --git a/detox/test/src/Screens/TimeoutsScreen.js b/detox/test/src/Screens/TimeoutsScreen.js index 0a25e9dba7..81c0899d59 100644 --- a/detox/test/src/Screens/TimeoutsScreen.js +++ b/detox/test/src/Screens/TimeoutsScreen.js @@ -21,27 +21,27 @@ export default class TimeoutsScreen extends Component { - Short Timeout + Short Timeout - Zero Timeout + Zero Timeout - Short Timeout Ignore + Short Timeout Ignore - Long Timeout Ignore + Long Timeout Ignore - Immediate + Immediate - Interval Ignore + Interval Ignore diff --git a/detox/test/src/Screens/WaitForScreen.js b/detox/test/src/Screens/WaitForScreen.js index a9c3107611..09626ac110 100644 --- a/detox/test/src/Screens/WaitForScreen.js +++ b/detox/test/src/Screens/WaitForScreen.js @@ -38,14 +38,14 @@ export default class WaitForScreen extends Component { - Text1 - Text2 - Text3 - Text4 - Text5 - Text6 - Text7 - Text8 + Text1 + Text2 + Text3 + Text4 + Text5 + Text6 + Text7 + Text8 From ad429502d83bf394f439c89219bfcc8cbb00d40c Mon Sep 17 00:00:00 2001 From: Simon Racz Date: Tue, 26 Sep 2017 14:41:14 +0200 Subject: [PATCH 3/4] Updated docs about label. Updated detox init script. --- README.md | 2 +- detox/local-cli/templates/mocha.js | 4 ++-- detox/src/android/expect.js | 2 +- docs/APIRef.Expect.md | 8 ++++++++ docs/APIRef.Matchers.md | 11 ++++++++++- docs/Troubleshooting.RunningTests.md | 4 ++-- examples/demo-native-android/e2e/example.spec.js | 14 +++++++------- examples/demo-react-native/e2e/example.spec.js | 4 ++-- 8 files changed, 33 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index a22f188a93..c4c282dc07 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ describe('Login flow', () => { await element(by.id('password')).typeText('123456'); await element(by.label('Login')).tap(); - await expect(element(by.label('Welcome'))).toBeVisible(); + await expect(element(by.text('Welcome'))).toBeVisible(); await expect(element(by.id('email'))).toNotExist(); }); diff --git a/detox/local-cli/templates/mocha.js b/detox/local-cli/templates/mocha.js index 2b90eada8b..72d4f32eed 100644 --- a/detox/local-cli/templates/mocha.js +++ b/detox/local-cli/templates/mocha.js @@ -10,12 +10,12 @@ const firstTestContent = `describe('Example', () => { it('should show hello screen after tap', async () => { await element(by.id('hello_button')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('should show world screen after tap', async () => { await element(by.id('world_button')).tap(); - await expect(element(by.label('World!!!'))).toBeVisible(); + await expect(element(by.text('World!!!'))).toBeVisible(); }); })` const initjsContent = `require('babel-polyfill'); diff --git a/detox/src/android/expect.js b/detox/src/android/expect.js index 5619731fb1..8168262e6f 100644 --- a/detox/src/android/expect.js +++ b/detox/src/android/expect.js @@ -283,7 +283,7 @@ class ExpectElement extends Expect { return await new MatcherAssertionInteraction(this._element, new TextMatcher(value)).execute(); } async toHaveLabel(value) { - return await new MatcherAssertionInteraction(this._element, new TextMatcher(value)).execute(); + return await new MatcherAssertionInteraction(this._element, new LabelMatcher(value)).execute(); } async toHaveId(value) { return await new MatcherAssertionInteraction(this._element, new IdMatcher(value)).execute(); diff --git a/docs/APIRef.Expect.md b/docs/APIRef.Expect.md index 6df28dc51e..9bd4f04afb 100644 --- a/docs/APIRef.Expect.md +++ b/docs/APIRef.Expect.md @@ -11,6 +11,7 @@ Expect verifies if a certain value is as expected to be. - [`.toExist()`](#toexist) - [`.toNotExist()`](#tonotexist) - [`.toHaveText()`](#tohavetexttext) +- [`.toHaveLabel()`](#tohavelabellabel) - [`.toHaveId()`](#tohaveidid) - [`.toHaveValue()`](#tohavevaluevalue) @@ -52,6 +53,13 @@ await expect(element(by.id('RandomJunk959'))).toNotExist(); await expect(element(by.id('UniqueId204'))).toHaveText('I contain some text'); ``` +### `toHaveLabel(label)` +- Similar to `toHaveText(text)`, but searches by accessibilityLabel (iOS) or by contentDescription (Android) + +```js +await expect(element(by.id('UniqueId204'))).toHaveLabel('Done'); +``` + ### `toHaveId(id)` - In React Native apps, expect UI component to have [`testID`](https://facebook.github.io/react-native/docs/view.html#testid) with that id. - In native iOS apps, expect UI element to have accesibilityIdentifier with that id. diff --git a/docs/APIRef.Matchers.md b/docs/APIRef.Matchers.md index bf1d549393..1acd3777e1 100644 --- a/docs/APIRef.Matchers.md +++ b/docs/APIRef.Matchers.md @@ -11,6 +11,7 @@ Matchers find elements in your app that match one or more properties. - [`by.id()`](#byidid) - [`by.text()`](#bytexttext) +- [`by.label()`](#bylabellabel) - [`by.type()`](#bytypenativeviewtype) - [`by.traits()`](#bytraitstraits) @@ -42,6 +43,14 @@ Find an element by text, useful for text fields, buttons. ```js await element(by.text('Tap Me')); ``` + +#### `by.label(label)` +Find an element by accessibilityLabel(iOS) or contentDescription(Android), useful for text fields, buttons. + +```js +await element(by.label('Welcome')); +``` + #### `by.type(nativeViewType)` Find an element by native view type. @@ -49,7 +58,7 @@ Find an element by native view type. await element(by.type('RCTImageView')); ``` #### `by.traits([traits])` -Find an element with an accessibility trait. +Find an element with an accessibility trait. (iOS only) ```js await element(by.traits(['button'])); diff --git a/docs/Troubleshooting.RunningTests.md b/docs/Troubleshooting.RunningTests.md index 3e39aa145d..a508ec807b 100644 --- a/docs/Troubleshooting.RunningTests.md +++ b/docs/Troubleshooting.RunningTests.md @@ -125,7 +125,7 @@ render() { ```js await element(by.label('Login')).tap(); -await expect(element(by.label('Welcome'))).toBeVisible(); +await expect(element(by.text('Welcome'))).toBeVisible(); ``` In the test above, after tapping the Login button, the app performs several complex asynchronous operations until the Welcome message is displayed post-login. These can include querying a server, waiting for a response and then running an animated transition to the Welcome screen. Detox attempts to simplify your test code by synchronizing *automatically* with these asynchronous operations. What happens if for some reason the automatic synchronization doesn't work? As a result, Detox will not wait correctly until the Welcome screen appears and instead will continue immediately to the next line and try to run the expectation. Since the screen is not there yet, the test will fail. @@ -136,7 +136,7 @@ Full documentation about `waitFor` is available [here](/docs/APIRef.waitFor.md). ```js await element(by.label('Login')).tap(); -await waitFor(element(by.label('Welcome'))).toBeVisible().withTimeout(2000); +await waitFor(element(by.text('Welcome'))).toBeVisible().withTimeout(2000); ```
diff --git a/examples/demo-native-android/e2e/example.spec.js b/examples/demo-native-android/e2e/example.spec.js index a69b71e8f3..924f31e60a 100644 --- a/examples/demo-native-android/e2e/example.spec.js +++ b/examples/demo-native-android/e2e/example.spec.js @@ -5,19 +5,19 @@ describe('Example', function () { }); it('should have welcome screen', function () { - expect(element(by.label('Welcome'))).toBeVisible(); - expect(element(by.label('Say Hello'))).toBeVisible(); - expect(element(by.label('Say World'))).toBeVisible(); + expect(element(by.text('Welcome'))).toBeVisible(); + expect(element(by.text('Say Hello'))).toBeVisible(); + expect(element(by.text('Say World'))).toBeVisible(); }); it('should show hello screen after tap', function () { - element(by.label('Say Hello')).tap(); - expect(element(by.label('Hello!!!'))).toBeVisible(); + element(by.text('Say Hello')).tap(); + expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('should show world screen after tap', function () { - element(by.label('Say World')).tap(); - expect(element(by.label('World!!!'))).toBeVisible(); + element(by.text('Say World')).tap(); + expect(element(by.text('World!!!'))).toBeVisible(); }); }); diff --git a/examples/demo-react-native/e2e/example.spec.js b/examples/demo-react-native/e2e/example.spec.js index ebffa3d0fc..caa08866a0 100644 --- a/examples/demo-react-native/e2e/example.spec.js +++ b/examples/demo-react-native/e2e/example.spec.js @@ -9,11 +9,11 @@ describe('Example', () => { it('should show hello screen after tap', async () => { await element(by.id('hello_button')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('should show world screen after tap', async () => { await element(by.id('world_button')).tap(); - await expect(element(by.label('World!!!'))).toBeVisible(); + await expect(element(by.text('World!!!'))).toBeVisible(); }); }); \ No newline at end of file From 37b5c40578201be3fb5793307aef60c8a163f9b8 Mon Sep 17 00:00:00 2001 From: Simon Racz Date: Wed, 27 Sep 2017 21:47:31 +0200 Subject: [PATCH 4/4] label -> text nearly everywhere --- README.md | 2 +- detox/test/e2e/a-sanity.js | 12 ++++----- detox/test/e2e/b-matchers.js | 10 +++---- detox/test/e2e/c-actions.js | 28 ++++++++++---------- detox/test/e2e/d-assertions.js | 4 +-- detox/test/e2e/e-waitfor.js | 8 +++--- detox/test/e2e/f-device.js | 26 +++++++++--------- detox/test/e2e/g-stress-tests.js | 18 ++++++------- detox/test/e2e/h-stress-root.js | 6 ++--- detox/test/e2e/i-stress-timeouts.js | 2 +- detox/test/e2e/j-async-and-callbacks.js | 6 ++--- detox/test/e2e/l-animations.js | 2 +- detox/test/e2e/l-permissions.js | 4 +-- detox/test/e2e/m-network.js | 2 +- detox/test/e2e/o-location.js | 4 +-- detox/test/package.json | 4 +-- detox/test/src/Screens/ActionsScreen.js | 20 +++++++------- detox/test/src/Screens/MatchersScreen.js | 2 +- detox/test/src/Screens/NetworkScreen.js | 4 +-- detox/test/src/Screens/Orientation.js | 2 +- detox/test/src/Screens/SanityScreen.js | 4 +-- detox/test/src/Screens/StressScreen.js | 4 +-- detox/test/src/Screens/SwitchRootScreen.js | 4 +-- detox/test/src/Screens/TimeoutsScreen.js | 12 ++++----- detox/test/src/Screens/WaitForScreen.js | 16 +++++------ detox/test/src/app.js | 2 +- docs/APIRef.Expect.md | 4 ++- docs/APIRef.Matchers.md | 2 +- docs/APIRef.MockingOpenFromURL.md | 2 +- docs/APIRef.MockingUserNotifications.md | 4 +-- docs/Guide.Migration.md | 16 +++++------ docs/Troubleshooting.RunningTests.md | 4 +-- examples/demo-native-ios/e2e/example.spec.js | 14 +++++----- 33 files changed, 128 insertions(+), 126 deletions(-) diff --git a/README.md b/README.md index c4c282dc07..b3fc7e0d18 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ describe('Login flow', () => { await element(by.id('email')).typeText('john@example.com'); await element(by.id('password')).typeText('123456'); - await element(by.label('Login')).tap(); + await element(by.text('Login')).tap(); await expect(element(by.text('Welcome'))).toBeVisible(); await expect(element(by.id('email'))).toNotExist(); diff --git a/detox/test/e2e/a-sanity.js b/detox/test/e2e/a-sanity.js index 3117b5d863..6e7bdc1fe4 100644 --- a/detox/test/e2e/a-sanity.js +++ b/detox/test/e2e/a-sanity.js @@ -4,22 +4,22 @@ describe('Sanity', () => { }); beforeEach(async () => { - await element(by.label('Sanity')).tap(); + await element(by.text('Sanity')).tap(); }); it('should have welcome screen', async () => { - await expect(element(by.label('Welcome'))).toBeVisible(); - await expect(element(by.label('Say Hello'))).toBeVisible(); - await expect(element(by.label('Say World'))).toBeVisible(); + await expect(element(by.text('Welcome'))).toBeVisible(); + await expect(element(by.text('Say Hello'))).toBeVisible(); + await expect(element(by.text('Say World'))).toBeVisible(); }); it('should show hello screen after tap', async () => { - await element(by.label('Say Hello')).tap(); + await element(by.text('Say Hello')).tap(); await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('should show world screen after tap', async () => { - await element(by.label('Say World')).tap(); + await element(by.text('Say World')).tap(); await expect(element(by.text('World!!!'))).toBeVisible(); }); }); diff --git a/detox/test/e2e/b-matchers.js b/detox/test/e2e/b-matchers.js index dafac3f709..cdb4318c37 100644 --- a/detox/test/e2e/b-matchers.js +++ b/detox/test/e2e/b-matchers.js @@ -1,7 +1,7 @@ describe('Matchers', () => { beforeEach(async () => { await device.reloadReactNative(); - await element(by.label('Matchers')).tap(); + await element(by.text('Matchers')).tap(); }); it('should match elements by (accesibility) label', async () => { @@ -26,7 +26,7 @@ describe('Matchers', () => { // Accessibility Inspector in the simulator can help investigate traits it(':ios: should match elements by accesibility trait', async () => { await element(by.traits(['button', 'text'])).tap(); - await expect(element(by.label('Traits Working!!!'))).toBeVisible(); + await expect(element(by.text('Traits Working!!!'))).toBeVisible(); }); it('should match elements with ancenstor (parent)', async () => { @@ -48,13 +48,13 @@ describe('Matchers', () => { }); it('should match elements by using two matchers together with and', async () => { - await expect(element(by.id('UniqueId345').and(by.label('ID')))).toExist(); - await expect(element(by.id('UniqueId345').and(by.label('RandomJunk')))).toNotExist(); + await expect(element(by.id('UniqueId345').and(by.text('ID')))).toExist(); + await expect(element(by.id('UniqueId345').and(by.text('RandomJunk')))).toNotExist(); }); // waiting to upgrade EarlGrey version in order to test this (not supported in our current one) it.skip('should choose from multiple elements matching the same matcher using index', async () => { - await expect(element(by.label('Product')).atIndex(2)).toHaveId('ProductId002'); + await expect(element(by.text('Product')).atIndex(2)).toHaveId('ProductId002'); }); }); diff --git a/detox/test/e2e/c-actions.js b/detox/test/e2e/c-actions.js index 8b5da35278..aa203c527c 100644 --- a/detox/test/e2e/c-actions.js +++ b/detox/test/e2e/c-actions.js @@ -4,16 +4,16 @@ describe('Actions', () => { }); beforeEach(async () => { - await element(by.label('Actions')).tap(); + await element(by.text('Actions')).tap(); }); it('should tap on an element', async () => { - await element(by.label('Tap Me')).tap(); + await element(by.text('Tap Me')).tap(); await expect(element(by.text('Tap Working!!!'))).toBeVisible(); }); it('should long press on an element', async () => { - await element(by.label('Tap Me')).longPress(); + await element(by.text('Tap Me')).longPress(); await expect(element(by.text('Long Press Working!!!'))).toBeVisible(); }); @@ -48,30 +48,30 @@ describe('Actions', () => { // directions: 'up'/'down'/'left'/'right' it('should scroll for a small amount in direction', async () => { - await expect(element(by.label('Text1'))).toBeVisible(); - await expect(element(by.label('Text4'))).toBeNotVisible(); + await expect(element(by.text('Text1'))).toBeVisible(); + await expect(element(by.text('Text4'))).toBeNotVisible(); await expect(element(by.id('ScrollView161'))).toBeVisible(); await element(by.id('ScrollView161')).scroll(100, 'down'); - await expect(element(by.label('Text1'))).toBeNotVisible(); - await expect(element(by.label('Text4'))).toBeVisible(); + await expect(element(by.text('Text1'))).toBeNotVisible(); + await expect(element(by.text('Text4'))).toBeVisible(); await element(by.id('ScrollView161')).scroll(100, 'up'); - await expect(element(by.label('Text1'))).toBeVisible(); - await expect(element(by.label('Text4'))).toBeNotVisible(); + await expect(element(by.text('Text1'))).toBeVisible(); + await expect(element(by.text('Text4'))).toBeNotVisible(); }); it('should scroll for a large amount in direction', async () => { - await expect(element(by.label('Text6'))).toBeNotVisible(); + await expect(element(by.text('Text6'))).toBeNotVisible(); await element(by.id('ScrollView161')).scroll(200, 'down'); - await expect(element(by.label('Text6'))).toBeVisible(); + await expect(element(by.text('Text6'))).toBeVisible(); }); // edges: 'top'/'bottom'/'left'/'right' it('should scroll to edge', async () => { - await expect(element(by.label('Text8'))).toBeNotVisible(); + await expect(element(by.text('Text8'))).toBeNotVisible(); await element(by.id('ScrollView161')).scrollTo('bottom'); - await expect(element(by.label('Text8'))).toBeVisible(); + await expect(element(by.text('Text8'))).toBeVisible(); await element(by.id('ScrollView161')).scrollTo('top'); - await expect(element(by.label('Text1'))).toBeVisible(); + await expect(element(by.text('Text1'))).toBeVisible(); }); // TODO - swipe is not good enough for triggering pull to refresh. need to come up with something better diff --git a/detox/test/e2e/d-assertions.js b/detox/test/e2e/d-assertions.js index cfb7617011..29c05a60c7 100644 --- a/detox/test/e2e/d-assertions.js +++ b/detox/test/e2e/d-assertions.js @@ -4,7 +4,7 @@ describe('Assertions', () => { }); beforeEach(async () => { - await element(by.label('Assertions')).tap(); + await element(by.text('Assertions')).tap(); }); it('should assert an element is visible', async () => { @@ -35,7 +35,7 @@ describe('Assertions', () => { }); it('should assert an element has (accessibility) id', async () => { - await expect(element(by.label('I contain some text'))).toHaveId('UniqueId204'); + await expect(element(by.text('I contain some text'))).toHaveId('UniqueId204'); }); // for example, the value of a UISwitch in the "on" state is "1" diff --git a/detox/test/e2e/e-waitfor.js b/detox/test/e2e/e-waitfor.js index 2900756fee..90fac31b8b 100644 --- a/detox/test/e2e/e-waitfor.js +++ b/detox/test/e2e/e-waitfor.js @@ -1,7 +1,7 @@ describe('WaitFor', () => { beforeEach(async() => { await device.reloadReactNative(); - await element(by.label('WaitFor')).tap(); + await element(by.text('WaitFor')).tap(); }); it('should wait until an element is created and exists in layout', async () => { @@ -23,9 +23,9 @@ describe('WaitFor', () => { }); it('should find element by scrolling until it is visible', async() => { - await expect(element(by.label('Text5'))).toBeNotVisible(); - await waitFor(element(by.label('Text5'))).toBeVisible().whileElement(by.id('ScrollView630')).scroll(50, 'down'); - await expect(element(by.label('Text5'))).toBeVisible(); + await expect(element(by.text('Text5'))).toBeNotVisible(); + await waitFor(element(by.text('Text5'))).toBeVisible().whileElement(by.id('ScrollView630')).scroll(50, 'down'); + await expect(element(by.text('Text5'))).toBeVisible(); }); }); diff --git a/detox/test/e2e/f-device.js b/detox/test/e2e/f-device.js index 8389bf27ef..7b1bc0a54e 100644 --- a/detox/test/e2e/f-device.js +++ b/detox/test/e2e/f-device.js @@ -1,22 +1,22 @@ describe('Device', () => { it('reloadReactNative - should tap successfully', async () => { await device.reloadReactNative(); - await element(by.label('Sanity')).tap(); - await element(by.label('Say Hello')).tap(); + await element(by.text('Sanity')).tap(); + await element(by.text('Say Hello')).tap(); await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('relaunchApp - should tap successfully', async () => { await device.relaunchApp(); - await element(by.label('Sanity')).tap(); - await element(by.label('Say Hello')).tap(); + await element(by.text('Sanity')).tap(); + await element(by.text('Say Hello')).tap(); await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('relaunchApp({delete: true}) - should tap successfully', async () => { await device.relaunchApp({delete: true}); - await element(by.label('Sanity')).tap(); - await element(by.label('Say Hello')).tap(); + await element(by.text('Sanity')).tap(); + await element(by.text('Say Hello')).tap(); await expect(element(by.text('Hello!!!'))).toBeVisible(); }); @@ -24,15 +24,15 @@ describe('Device', () => { await device.uninstallApp(); await device.installApp(); await device.relaunchApp(); - await element(by.label('Sanity')).tap(); - await element(by.label('Say Hello')).tap(); + await element(by.text('Sanity')).tap(); + await element(by.text('Say Hello')).tap(); await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('launchApp({newInstance: true}) + sendToHome() + launchApp() - should bring up previous instance', async () => { await device.launchApp({newInstance: true}); - await element(by.label('Sanity')).tap(); - await element(by.label('Say Hello')).tap(); + await element(by.text('Sanity')).tap(); + await element(by.text('Say Hello')).tap(); await device.sendToHome(); await device.launchApp(); @@ -43,15 +43,15 @@ describe('Device', () => { await device.resetContentAndSettings(); await device.installApp(); await device.launchApp({ newInstance: true }); - await element(by.label('Sanity')).tap(); - await element(by.label('Say Hello')).tap(); + await element(by.text('Sanity')).tap(); + await element(by.text('Say Hello')).tap(); await expect(element(by.text('Hello!!!'))).toBeVisible(); }); describe('device orientation', () => { beforeEach(async() => { await device.reloadReactNative(); - await element(by.label('Orientation')).tap(); + await element(by.text('Orientation')).tap(); // Check if the element which input we will test actually exists await expect(element(by.id('currentOrientation'))).toExist(); diff --git a/detox/test/e2e/g-stress-tests.js b/detox/test/e2e/g-stress-tests.js index b6362d6961..60d2c0c31f 100644 --- a/detox/test/e2e/g-stress-tests.js +++ b/detox/test/e2e/g-stress-tests.js @@ -4,30 +4,30 @@ describe('StressTests', () => { }); beforeEach(async () => { - await element(by.label('Stress')).tap(); + await element(by.text('Stress')).tap(); }); it('should handle tap during busy bridge (one way)', async () => { - await element(by.label('Bridge OneWay Stress')).tap(); - await element(by.label('Next')).tap(); + await element(by.text('Bridge OneWay Stress')).tap(); + await element(by.text('Next')).tap(); await expect(element(by.text('BridgeOneWay'))).toBeVisible(); }); it('should handle tap during busy bridge (two way)', async () => { - await element(by.label('Bridge TwoWay Stress')).tap(); - await element(by.label('Next')).tap(); + await element(by.text('Bridge TwoWay Stress')).tap(); + await element(by.text('Next')).tap(); await expect(element(by.text('BridgeTwoWay'))).toBeVisible(); }); it('should handle tap during busy bridge (setState)', async () => { - await element(by.label('Bridge setState Stress')).tap(); - await element(by.label('Next')).tap(); + await element(by.text('Bridge setState Stress')).tap(); + await element(by.text('Next')).tap(); await expect(element(by.text('BridgeSetState'))).toBeVisible(); }); it('should handle tap during busy JS event loop', async () => { - await element(by.label('EventLoop Stress')).tap(); - await element(by.label('Next')).tap(); + await element(by.text('EventLoop Stress')).tap(); + await element(by.text('Next')).tap(); await expect(element(by.text('EventLoop'))).toBeVisible(); }); diff --git a/detox/test/e2e/h-stress-root.js b/detox/test/e2e/h-stress-root.js index d7e82382ba..ada1cae9ea 100644 --- a/detox/test/e2e/h-stress-root.js +++ b/detox/test/e2e/h-stress-root.js @@ -4,7 +4,7 @@ describe('StressRoot', () => { }); beforeEach(async () => { - await element(by.label('Switch Root')).tap(); + await element(by.text('Switch Root')).tap(); }); after(async () => { @@ -12,12 +12,12 @@ describe('StressRoot', () => { }); it('should switch root view controller from RN to native', async () => { - await element(by.label('Switch to a new native root')).tap(); + await element(by.text('Switch to a new native root')).tap(); await expect(element(by.text('this is a new native root'))).toBeVisible(); }); it(':ios: should switch root view controller from RN to RN', async () => { - await element(by.label('Switch to multiple react roots')).tap(); + await element(by.text('Switch to multiple react roots')).tap(); await expect(element(by.text('Choose a test'))).toBeVisible(); }); }); diff --git a/detox/test/e2e/i-stress-timeouts.js b/detox/test/e2e/i-stress-timeouts.js index 60f2e8d9b5..b7c8b54ffe 100644 --- a/detox/test/e2e/i-stress-timeouts.js +++ b/detox/test/e2e/i-stress-timeouts.js @@ -4,7 +4,7 @@ describe('StressTimeouts', () => { }); beforeEach(async () => { - await element(by.label('Timeouts')).tap(); + await element(by.text('Timeouts')).tap(); }); it(':ios: should handle a short timeout', async () => { diff --git a/detox/test/e2e/j-async-and-callbacks.js b/detox/test/e2e/j-async-and-callbacks.js index 6a51f7938f..4bd4d68c23 100644 --- a/detox/test/e2e/j-async-and-callbacks.js +++ b/detox/test/e2e/j-async-and-callbacks.js @@ -1,11 +1,11 @@ describe('Async and Callbacks', () => { beforeEach(async () => { await device.reloadReactNative(); - await element(by.label('Sanity')).tap(); + await element(by.text('Sanity')).tap(); }); it('should handle done() callback', (done) => { - expect(element(by.label('Welcome'))).toBeVisible().then(() => { + expect(element(by.text('Welcome'))).toBeVisible().then(() => { setTimeout(() => { done(); }, 1000); @@ -14,7 +14,7 @@ describe('Async and Callbacks', () => { it('should handle async await', async () => { await timeout(1); - await expect(element(by.label('Welcome'))).toBeVisible(); + await expect(element(by.text('Welcome'))).toBeVisible(); }); }); diff --git a/detox/test/e2e/l-animations.js b/detox/test/e2e/l-animations.js index 8f13d1439a..9a5c46fcaf 100644 --- a/detox/test/e2e/l-animations.js +++ b/detox/test/e2e/l-animations.js @@ -3,7 +3,7 @@ let _ = require('lodash'); describe('Animations', () => { beforeEach(async () => { await device.reloadReactNative(); - await element(by.label('Animations')).tap(); + await element(by.text('Animations')).tap(); }); async function _startTest(driver, options = {}) { diff --git a/detox/test/e2e/l-permissions.js b/detox/test/e2e/l-permissions.js index ad8008133b..3f317cfdf1 100644 --- a/detox/test/e2e/l-permissions.js +++ b/detox/test/e2e/l-permissions.js @@ -2,13 +2,13 @@ describe('Permissions', () => { it('Permissions is granted', async () => { await device.launchApp({permissions: {calendar: 'YES'}}); - await element(by.label('Permissions')).tap(); + await element(by.text('Permissions')).tap(); await expect(element(by.text('granted'))).toBeVisible(); }); it('Permissions denied', async () => { await device.launchApp({permissions: {calendar: 'NO'}}); - await element(by.label('Permissions')).tap(); + await element(by.text('Permissions')).tap(); await expect(element(by.text('denied'))).toBeVisible(); }); }); \ No newline at end of file diff --git a/detox/test/e2e/m-network.js b/detox/test/e2e/m-network.js index 55fe709788..e572385d15 100644 --- a/detox/test/e2e/m-network.js +++ b/detox/test/e2e/m-network.js @@ -13,7 +13,7 @@ describe('Network Synchronization', () => { beforeEach(async () => { await device.reloadReactNative(); - await element(by.label('Network')).tap(); + await element(by.text('Network')).tap(); }); it('Sync with short network requests - 100ms', async () => { diff --git a/detox/test/e2e/o-location.js b/detox/test/e2e/o-location.js index 7c8516023f..c7ed469056 100644 --- a/detox/test/e2e/o-location.js +++ b/detox/test/e2e/o-location.js @@ -17,7 +17,7 @@ describe('location', () => { return; } await device.relaunchApp({ permissions: { location: 'never' } }); - await element(by.label('Location')).tap(); + await element(by.text('Location')).tap(); await element(by.id('getLocationButton')).tap(); await expect(element(by.id('error'))).toBeVisible(); }); @@ -30,7 +30,7 @@ describe('location', () => { } await device.relaunchApp({ permissions: { location: 'always' } }); await device.setLocation(20, 20); - await element(by.label('Location')).tap(); + await element(by.text('Location')).tap(); await element(by.id('getLocationButton')).tap(); await waitFor(element(by.text('Latitude: 20'))).toBeVisible().withTimeout(3000); diff --git a/detox/test/package.json b/detox/test/package.json index 452682be15..019a91bc2c 100644 --- a/detox/test/package.json +++ b/detox/test/package.json @@ -49,7 +49,7 @@ "binaryPath": "android/app/build/outputs/apk/app-debug.apk", "build": "pushd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && popd", "type": "android.emulator", - "name": "Nexus_5X_API_24_-_GPlay", + "name": "Nexus_5X_API_24", "session": { "server": "ws://localhost:8099", "sessionId": "test" @@ -59,7 +59,7 @@ "binaryPath": "android/app/build/outputs/apk/app-release.apk", "build": "pushd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && popd", "type": "android.emulator", - "name": "Nexus_5X_API_24_-_GPlay", + "name": "Nexus_5X_API_24", "session": { "server": "ws://localhost:8099", "sessionId": "test" diff --git a/detox/test/src/Screens/ActionsScreen.js b/detox/test/src/Screens/ActionsScreen.js index e5d9080e78..0d534e4c50 100644 --- a/detox/test/src/Screens/ActionsScreen.js +++ b/detox/test/src/Screens/ActionsScreen.js @@ -29,12 +29,12 @@ export default class ActionsScreen extends Component { - Tap Me + Tap Me - Tap Me For Long Timeout + Tap Me For Long Timeout @@ -62,14 +62,14 @@ export default class ActionsScreen extends Component { - Text1 - Text2 - Text3 - Text4 - Text5 - Text6 - Text7 - Text8 + Text1 + Text2 + Text3 + Text4 + Text5 + Text6 + Text7 + Text8 diff --git a/detox/test/src/Screens/MatchersScreen.js b/detox/test/src/Screens/MatchersScreen.js index f1a28cc2af..57b571d324 100644 --- a/detox/test/src/Screens/MatchersScreen.js +++ b/detox/test/src/Screens/MatchersScreen.js @@ -25,7 +25,7 @@ export default class MatchersScreen extends Component { - ID + ID diff --git a/detox/test/src/Screens/NetworkScreen.js b/detox/test/src/Screens/NetworkScreen.js index f988f4a6c9..994ccab135 100644 --- a/detox/test/src/Screens/NetworkScreen.js +++ b/detox/test/src/Screens/NetworkScreen.js @@ -24,11 +24,11 @@ export default class NetworkScreen extends Component { - Short Network Request + Short Network Request - Long Network Request + Long Network Request ); diff --git a/detox/test/src/Screens/Orientation.js b/detox/test/src/Screens/Orientation.js index 35f5bba2ba..9d91402679 100644 --- a/detox/test/src/Screens/Orientation.js +++ b/detox/test/src/Screens/Orientation.js @@ -24,7 +24,7 @@ export default class Orientation extends Component { render() { return ( - + {this.state.horizontal ? 'Landscape' : 'Portrait'} diff --git a/detox/test/src/Screens/SanityScreen.js b/detox/test/src/Screens/SanityScreen.js index 2baabeb6f8..494a36d71d 100644 --- a/detox/test/src/Screens/SanityScreen.js +++ b/detox/test/src/Screens/SanityScreen.js @@ -18,7 +18,7 @@ export default class SanityScreen extends Component { renderTestButton(label, onPress) { return ( - {label} + {label} ) } @@ -27,7 +27,7 @@ export default class SanityScreen extends Component { if (this.state.greeting) return this.renderAfterButton(); return ( - + Welcome {this.renderTestButton('Say Hello', this.onButtonPress.bind(this, 'Hello'))} diff --git a/detox/test/src/Screens/StressScreen.js b/detox/test/src/Screens/StressScreen.js index 15f0ce9a45..45b4bf5fda 100644 --- a/detox/test/src/Screens/StressScreen.js +++ b/detox/test/src/Screens/StressScreen.js @@ -61,7 +61,7 @@ export default class StressScreen extends Component { renderTestButton(label, onPress) { return ( - {label} + {label} ) } @@ -100,7 +100,7 @@ export default class StressScreen extends Component { return ( - Next + Next ); diff --git a/detox/test/src/Screens/SwitchRootScreen.js b/detox/test/src/Screens/SwitchRootScreen.js index 00fb03a031..3ec8cf57ca 100644 --- a/detox/test/src/Screens/SwitchRootScreen.js +++ b/detox/test/src/Screens/SwitchRootScreen.js @@ -13,10 +13,10 @@ export default class SwitchRootScreen extends Component { return ( NativeModule.switchToNativeRoot()}> - {`Switch to a new native root`} + {`Switch to a new native root`} NativeModule.switchToMultipleReactRoots()}> - {`Switch to multiple react roots`} + {`Switch to multiple react roots`} ); diff --git a/detox/test/src/Screens/TimeoutsScreen.js b/detox/test/src/Screens/TimeoutsScreen.js index 81c0899d59..0a25e9dba7 100644 --- a/detox/test/src/Screens/TimeoutsScreen.js +++ b/detox/test/src/Screens/TimeoutsScreen.js @@ -21,27 +21,27 @@ export default class TimeoutsScreen extends Component { - Short Timeout + Short Timeout - Zero Timeout + Zero Timeout - Short Timeout Ignore + Short Timeout Ignore - Long Timeout Ignore + Long Timeout Ignore - Immediate + Immediate - Interval Ignore + Interval Ignore diff --git a/detox/test/src/Screens/WaitForScreen.js b/detox/test/src/Screens/WaitForScreen.js index 09626ac110..a9c3107611 100644 --- a/detox/test/src/Screens/WaitForScreen.js +++ b/detox/test/src/Screens/WaitForScreen.js @@ -38,14 +38,14 @@ export default class WaitForScreen extends Component { - Text1 - Text2 - Text3 - Text4 - Text5 - Text6 - Text7 - Text8 + Text1 + Text2 + Text3 + Text4 + Text5 + Text6 + Text7 + Text8 diff --git a/detox/test/src/app.js b/detox/test/src/app.js index 8d1b89879c..fa000aca38 100644 --- a/detox/test/src/app.js +++ b/detox/test/src/app.js @@ -24,7 +24,7 @@ class example extends Component { { this.setState({screen: component}); }}> - {title} + {title} ); } diff --git a/docs/APIRef.Expect.md b/docs/APIRef.Expect.md index 9bd4f04afb..c5af8c9a76 100644 --- a/docs/APIRef.Expect.md +++ b/docs/APIRef.Expect.md @@ -54,7 +54,9 @@ await expect(element(by.id('UniqueId204'))).toHaveText('I contain some text'); ``` ### `toHaveLabel(label)` -- Similar to `toHaveText(text)`, but searches by accessibilityLabel (iOS) or by contentDescription (Android) +- It searches by accessibilityLabel on iOS, or by contentDescription on Android. + +- In React Native it can be set for both platforms by defining an [`accessibilityLabel`](https://facebook.github.io/react-native/docs/view.html#accessibilitylabel) on the view. ```js await expect(element(by.id('UniqueId204'))).toHaveLabel('Done'); diff --git a/docs/APIRef.Matchers.md b/docs/APIRef.Matchers.md index 1acd3777e1..0a725f6c92 100644 --- a/docs/APIRef.Matchers.md +++ b/docs/APIRef.Matchers.md @@ -45,7 +45,7 @@ await element(by.text('Tap Me')); ``` #### `by.label(label)` -Find an element by accessibilityLabel(iOS) or contentDescription(Android), useful for text fields, buttons. +Find an element by `accessibilityLabel` on iOS, or by `contentDescription` on Android. ```js await element(by.label('Welcome')); diff --git a/docs/APIRef.MockingOpenFromURL.md b/docs/APIRef.MockingOpenFromURL.md index 0304cf0f28..f665b6aaa4 100644 --- a/docs/APIRef.MockingOpenFromURL.md +++ b/docs/APIRef.MockingOpenFromURL.md @@ -17,7 +17,7 @@ describe('relaunchApp', () => { }); it('should tap successfully', async () => { - await expect(element(by.label('a label'))).toBeVisible(); + await expect(element(by.text('a label'))).toBeVisible(); }); }); ``` diff --git a/docs/APIRef.MockingUserNotifications.md b/docs/APIRef.MockingUserNotifications.md index d3baa755ae..9ab4032e7f 100644 --- a/docs/APIRef.MockingUserNotifications.md +++ b/docs/APIRef.MockingUserNotifications.md @@ -21,7 +21,7 @@ describe('Background push notification', () => { }); it('push notification from background', async () => { - await expect(element(by.label('From push'))).toBeVisible(); + await expect(element(by.text('From push'))).toBeVisible(); }); }); ``` @@ -46,7 +46,7 @@ beforeEach(async () => { it('Local notification from inside the app', async () => { await device.sendUserNotification(localNotification); - await expect(element(by.label('from local notificaton'))).toBeVisible(); + await expect(element(by.text('from local notificaton'))).toBeVisible(); }); }); ``` diff --git a/docs/Guide.Migration.md b/docs/Guide.Migration.md index e4e790f108..46fd181872 100644 --- a/docs/Guide.Migration.md +++ b/docs/Guide.Migration.md @@ -16,7 +16,7 @@ Here's an example of async call to tap an element ```js // <=4.x.x beforeEach(() => { - element(by.label('Sanity')).tap(); + element(by.text('Sanity')).tap(); }); ``` @@ -24,7 +24,7 @@ beforeEach(() => { ```js // 5.x.x beforeEach(async () => { - await element(by.label('Sanity')).tap(); + await element(by.text('Sanity')).tap(); }); ``` @@ -33,18 +33,18 @@ Same thing with expectations ```js // <=4.x.x it('should have welcome screen', () => { - expect(element(by.label('Welcome'))).toBeVisible(); - expect(element(by.label('Say Hello'))).toBeVisible(); - expect(element(by.label('Say World'))).toBeVisible(); + expect(element(by.text('Welcome'))).toBeVisible(); + expect(element(by.text('Say Hello'))).toBeVisible(); + expect(element(by.text('Say World'))).toBeVisible(); }; ``` ```js // 5.x.x it('should have welcome screen', async () => { - await expect(element(by.label('Welcome'))).toBeVisible(); - await expect(element(by.label('Say Hello'))).toBeVisible(); - await expect(element(by.label('Say World'))).toBeVisible(); + await expect(element(by.text('Welcome'))).toBeVisible(); + await expect(element(by.text('Say Hello'))).toBeVisible(); + await expect(element(by.text('Say World'))).toBeVisible(); }); ``` diff --git a/docs/Troubleshooting.RunningTests.md b/docs/Troubleshooting.RunningTests.md index a508ec807b..59027d2357 100644 --- a/docs/Troubleshooting.RunningTests.md +++ b/docs/Troubleshooting.RunningTests.md @@ -124,7 +124,7 @@ render() { **Issue:** Due to a synchronization issue, the test tries to perform an expectation and fails because it runs the expectation too soon. Consider this example: ```js -await element(by.label('Login')).tap(); +await element(by.text('Login')).tap(); await expect(element(by.text('Welcome'))).toBeVisible(); ``` @@ -135,7 +135,7 @@ In the test above, after tapping the Login button, the app performs several comp Full documentation about `waitFor` is available [here](/docs/APIRef.waitFor.md). This is what the fixed test would look like: ```js -await element(by.label('Login')).tap(); +await element(by.text('Login')).tap(); await waitFor(element(by.text('Welcome'))).toBeVisible().withTimeout(2000); ``` diff --git a/examples/demo-native-ios/e2e/example.spec.js b/examples/demo-native-ios/e2e/example.spec.js index 7190b44a03..117270b364 100644 --- a/examples/demo-native-ios/e2e/example.spec.js +++ b/examples/demo-native-ios/e2e/example.spec.js @@ -4,18 +4,18 @@ describe('Example', () => { }); it('should have welcome screen', async () => { - await expect(element(by.label('Welcome'))).toBeVisible(); - await expect(element(by.label('Say Hello'))).toBeVisible(); - await expect(element(by.label('Say World'))).toBeVisible(); + await expect(element(by.text('Welcome'))).toBeVisible(); + await expect(element(by.text('Say Hello'))).toBeVisible(); + await expect(element(by.text('Say World'))).toBeVisible(); }); it('should show hello screen after tap', async () => { - await element(by.label('Say Hello')).tap(); - await expect(element(by.label('Hello!!!'))).toBeVisible(); + await element(by.text('Say Hello')).tap(); + await expect(element(by.text('Hello!!!'))).toBeVisible(); }); it('should show world screen after tap', async () => { - await element(by.label('Say World')).tap(); - await expect(element(by.label('World!!!'))).toBeVisible(); + await element(by.text('Say World')).tap(); + await expect(element(by.text('World!!!'))).toBeVisible(); }); });