Part 2: UI Testing on Firefox OS. Working with iframes


by Zac Campbell

In Part 2 we’ll talk about how Firefox OS uses the iframe HTML element for displaying apps. This behaviour is quite different to a typical webpage.

If you’ve already used Firefox OS thus far then you’ll realise that it is a web browser on your phone. To take it to the next level, Firefox OS is one big web page, in a web browser on your phone.

On a desktop computer you open each webpage or a web app in a different window or tab. On Firefox OS each web app will be opened in a new iframe. This is good for security – it ‘sandboxes’ apps – but it can be a bother for testing. We need to switch between the iframes depending upon which app we need to be testing at that time.

This frame switching functionality exists in desktop variation of web pages and is supported by WebDriver, however it is rarely used. The user and design requirements of Firefox OS mean that iframes are about to undergo a resurrection!

Firefox OS Calendar frame

This diagram depicts the Calendar app loaded inside Firefox OS. The Calendar app iframe is a child of the Firefox OS system frame. In this basic example we want to run tests against the Calendar. After the app is loaded, we’ll need to instruct marionette to switch into it before we can find and interact with its elements:

# The Calendar app is already running
# Now we are in the System level frame
# Let’s find the Calendar frame
calendar_frame = self.marionette.find_element(‘css selector’,
# OK we’ve got the frame; now let’s switch into it.
# We can pass in the HTMLElement
# Let’s check the title
print self.marionette.title
# Ready to run the test!

That wasn’t too bad! Now let’s look at a couple more examples the Mozilla Web QA team have experienced while developing automated UI tests for Firefox OS.

Firefox OS Browser frame

In this example diagram the app we are using is the Browser within Firefox. You may come across this example if you are using the Browser to test how your website will appear in the Firefox OS Browser.

The tricky part of this example is that there is another <iframe> nested inside the Browser itself and that is what contains the displayed website.

To access the URL bar, Go button and other browser-related interfaces we need to be in the Browser’s frame (the middle frame).

In this code example we’ll switch into the Browser, type in the URL bar, load the webpage then finally switch into the page iframe so we can read the webpage content.

# The Browser app is already running
# Let’s find the Browser frame
browser_frame = self.marionette.find_element(‘css selector’,
# OK we’ve got the frame; now let’s switch into it.
# Find the URL bar and insert a URL
url_bar = self.marionette.find_element(‘id’, ‘url-input’)
# Click the ‘go’ arrow and wait for the page to load
self.marionette.find_element(‘id’, ‘url-button’).single_tap()
# The page has loaded so we’ll switch into the frame
# where we can view the HTML
webpage_frame = self.marionette.find_element(‘css selector’,
# Now let’s check the title again
print self.marionette.title
Mozilla — Home of the Mozilla Project —

Phew, getting a bit trickier now with various layers to traverse! Now you’re in the website’s frame and can click links, get text and functionally test the site in the manner you’re familiar with from WebDriver.

In my final example I’ll switch to the keyboard UI to type an SMS message. This is a good example of how the system frames (as the keyboard is part of the operating system) and the app frames co-exist.

Firefox OS Keyboard frame

This test will load the SMS app and focus in the input message field, at which point Firefox OS will open the keyboard for you to type into the field (just imagine doing this as a user). However this test contains an important difference – when we switch to the Keyboard frame we want to do it without Firefox OS knowing. Otherwise, as the SMS app loses its focus the keyboard will close! Thus when we switch to the Keyboard frame we pass in focus=False which skips sending the focus event to Firefox OS. It will make sense in the example!

# The SMS app is already loaded
# Let’s find its frame
sms_frame = self.marionette.find_element(‘css selector’,
# OK we’ve got the frame; now let’s switch into it.
# Tap/click ‘+’ to start writing a new message
self.marionette.find_element(‘id’, ‘icon-add’).single_tap()
# Focussing into the SMS field will cause the Keyboard to pop open
self.marionette.find_element(‘id’, ‘receiver-input’).single_tap()
# Now we need to traverse up to the system frame
# and then back down into the Keyboard
# If we want to go to the system frame we use empty switch_to_frame
keyboard_frame = self.marionette.find_element(‘css selector’,
‘#keyboard-frame iframe’)
# The important bit: switch to the Keyboard without focus!
self.marionette.switch_to_frame(keyboard_frame, focus=False)

That’s it, now we’re in the keyboard frame. We can find the buttons, tap them and the key presses will be sent to the SMS app.

When you want to go back to the SMS app you will need to switch back up the iframe tree to the System frame then back down into the SMS app. The code can get long and tedious so try and keep your test cases short and simple.

NB: In everyday use you are more likely to use Marionette’s send_keys(), but just in case you have a need to type with the keyboard this is how you would do it!

As with all things in the world the best way to learn is to get out there and try it out yourself.

Next blog we’ll look at how Firefox OS apps are designed differently; instead of loading individual pages they use Ajax and CSS to change what visible in the viewport.