Join Samer Buna for an in-depth discussion in this video Testing on Android, part of React Native Essential Training.
- [Instructor] To test on Android, we need to have an emulator up and running, so let's do that. The Pixel emulator here is the one that we used, so let's start that. And once the emulator is up and running, we can go ahead and do react-native run-android. The application is loading, and things are working.
Let's have the remote debugger open, so command + m, and Debug JS Remotely. Very good, I don't see any problems. Let's test going to a single deal. How about the swipe feature? Swiping seems to work, although it is a little bit slow here on the emulator. This could be an emulator problem, so I'll try and test this on an actual device. However, there is an important problem that we did not see on a bigger device when we were testing with iOS is that this whole view is not scrollable, so I can't actually reach the button here on this smaller device.
This is not an Android-only problem but it's more obvious here. So this one is scrollable, and you can see the button here, but the other one, since the description of the deal is bigger, we are not seeing the button. So let's make this scrollable. All we we need to do in DealDetail component is this top-level view here that hosts the DealDetail component has to be a scroll view instead of just a view. So ScrollView, and /ScrollView, which means I need ScrollView from React Native as well.
Let's test that, hit the r key twice, and now this is scrollable. Very good. Let's also give it some margin down below here so that the button is not right on the edge. So I'll go ahead and do that. So styles.deal, which we do not have, so let's create, deal, and I'll just give it a marginBottom of say 20.
Let me test that real quick. Very good, so now we have a scrollable view and we can buy this deal. Let me go ahead and test that out. So it is going to http://bakesaleforgood.com on this deal, and a user can buy it. Let's test the search feature. It looks like it's working. However, I don't like that the keyboard here stayed when the search was performed.
So when the search is performed, we should probably get rid of the keyboard. So we can probably do that by just blurring out of the search. So let's try that in the search bar component. We have the text input here. We'll go ahead and give it a ref attribute. The ref attribute is a function, and this function is going to expose the input element here, and I'll go ahead and put it on the instance of this component, so this.inputElement = inputElement exposed from this function.
So now we can access the text input instance with this.inputElement. So what I want to do now is create a new function here. I'll call this function searchDeals. So this is the local function that is going to perform this.props.searchDeals, and after that it will blur the text input. So this is going to receive the search term and pass it along in here, and instead of debouncing this.props.searchDeals, we're going to debounce this.searchDeals, and to blur the text input, all we need to do is call this.inputElement.
This is the actual UI input element, and we can do .blur on it. So let's go ahead and test all that. R, r. Now we can search. When we search, the search is now blurred and I see the listing. Very good. Here is another problem. So let me show that. So I typed in a search, the search worked, it blurred out and the keyboard was dismissed, and now I pressed into one of the deals from the search.
Perfect, everything is working. When I go back, the search is still active, and the search term here was cleared out. So we can either not clear out the search term or reset the search when we click back. I think we should persist the search term because it will be interesting to keep the state of the search here so that I browse through multiple deals from the same search. However, this requires that we put the search term on the state of the App component here.
So I'm going to call it activeSearchTerm here, and the reason I named it active is that it is different from the search term that we have on the state of the search bar. This one is the local search term, and in fact we need to pass the active search term to the SearchBar component in here, so in here we'll name it initialSeachTerm and we'll pass that as this.state.activeSearchTerm.
Let me format. So this way if there is an active search term, and I remount this SearchBar component, it will have the initialSearchTerm property, so we'll go ahead and define that, initialSeachTerm is PropTypes.string, and it is required. I'm going to use it all the time. So the search term here doesn't start from an empty string. It starts from this.props.initialSearchTerm.
Very good. Now to finish this simple feature, when I actually perform the search, so in here, when I perform the search and bring back dealsFromSearch, I should also set the activeSearchTerm to be the search term that was passed to this method. So not only I have dealsFromSearch, I also have an activeSearchTerm that is going to persist through navigation. The other thing that we need to do here is to specify the value of the text input.
So the value of the text input is going to be connected to this.state.searchTerm, just like that, all the time, 'cause this is a controlled component. So let's test that out now. Search for yoga. Search is working. Click on this list, click back. The search is still there. Now we can change the search to something else. Click here, click back, and if I don't have any search, click here, click back.
All is good. So as you can see, I had bugs in the app and I had no idea that they existed, and the only way to find these bugs is to test every possible thing you can think about and get some other perspective. Usually, the person who writes the code is biased toward the happy cases. You want to get someone else to test your code, and it's much more likely that they are going to find some problems. This is why in the next video, we're going to prepare our production release of our app, push it through an Apple developer account, and use TestFlight to give it to others to test it.
So while testing things out after changing the main view in the DealDetailView into a scroll view, I got into this state. Now that we have a scrolling gesture, it seems that it's easy to conflict the swiping gesture with the scrolling gesture. If you just swipe horizontally, it works, but if you swipe and scroll, it doesn't. So there are a few ways to solve this, but the easiest is probably to not have the animated image within the scroll view.
So I'm going to change the scroll view back to just view, and I'll make the detail view right here into a scrollable view. So this is a ScrollView, View/View in here. Let me test that out. So now the image is swipable but it's not scrollable. You cannot scroll up and down. You can just swipe through. So you can't have the case that we had before because this is not scrollable now.
This is still scrollable. I think I'd even rather have the title not within the scrollable area, so I'm going to actually do that as well. I'll have the title in here. Let's see if that is going to affect any of the styling. So now the title is not scrollable. This area is scrollable, just like that, and the swipe is working perfectly. I definitely need to give this app to more people to test it on real devices, because I am pretty sure we have more problems that I am not aware of because of my biased testing.
- Hello React Native on iOS and Android
- Styling React Native components
- Platform APIs
- Building a simple game app and a data-driven app
- Using the Fetch API
- Creating an animation loop
- Testing on Android
- Changing an app logo and a splash screen
- Using TestFlight with internal testers