It's not very common, but it can happen that an Android hybrid app has not just one but two or more webviews (for example, when advertisements are in one webview and app logic is in another). If you've ever found yourself in this situation, you may have been frustrated when using Appium's context API, specifically with code like this:
If you have multiple webviews, you might have expected the Set to contain three items: NATIVE_APP, and two webview-looking strings. But instead you probably found only one webview context. If you were lucky, it was the one you wanted, but there was an equal chance you got the unimportant advertising webview (or whatever). So, how can we be sure to get inside the particular webview we want, even when there are multiple?
The answer lies in how Chromedriver works. Appium uses Chromedriver for Chrome automation, and Chromedriver handles multiple webviews in a single Android app by treating them as separate windows. What this means is that we have access to them using the built-in Webdriver window commands, like so:
Then, we can switch into any window we want by picking a certain handle:
How do we know from the handle which window to choose? We don't, because it will be a random-looking string like CDwindow-A26869B5EDAEAA9D83947BB274F1D0C7, and it might change from test to test. So our best bet is to switch into each one and perform some validation on the window, to prove that we are in the correct one (for example, looking at the URL or title as a way of ensuring we're in the right webview, and short-circuiting our search when we find it).
Of course, to do any of this we actually have to be in the webview context first, otherwise the getWindowHandles command won't do anything. So to conclude, here's a full example that utilizes a new feature of The App, namely a view with two webviews. The idea behind this test is simply to make an assertion based on the contents of the page displayed in each webview, proving that we can indeed enter and automate both of them. As with Edition 17, we use a helper function getWebContext to get ourselves into the initial web context so that Chromedriver is operative. Without further ado, here's the full sample:
That's it! With judicious use of both context and window handles commands, automating multiple webviews is totally doable. Don't forget to check out the full code on GitHub.