Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Part 2: Basic interactions with Firefox OS using Marionette

In part 2 of our tutorial we’ll get started with some simple Marionette commands that allow us to remotely control Firefox OS. While this doesn't cover writing a full test, it teaches you the basic code features that you will use while writing a test. In part 3, we’ll progress onto evolving this code into a real test.

Starting up Firefox OS

When writing these tests we’ll need to have Firefox OS already running and ready to receive commands:

  1. Start up desktop B2G.
  2. Disable the lock screen using Settings App > Screen lock > uncheck Lock screen.
  3. Disable screen timeout/sleep mode by changing the Settings App > Display > Screen timeout setting to never.
  4. Move the window over to the side to await our test commands.

Firing up Marionette

Now we will start a Python console: simply go to a Terminal window and issue the python command.

From here we can send commands to the Marionette server inside Firefox OS. After issuing many of the below commands you should see Firefox OS respond. In the Python console, enter the following command to import the Marionette library containing the code we need:

from marionette import Marionette

Now run the next two lines, which initiate a Marionette session, preparing Marionette to receive commands from the client:

marionette = Marionette()
marionette.start_session()

If you didn't disable the lock screen as explained above, you can unlock the screen programmatically, using this command:

marionette.execute_script('window.wrappedJSObject.lockScreen.unlock();')

Accessing different frames inside Firefox OS

Web apps in Firefox OS operate in different iFrames. Running web apps in separate frames gives them distinct containers for security and also visual management (like a window). You can think of it like a sandbox the app runs in. Marionette can only operate in one of the frames at a time. We need Marionette to switch into the frame that we’re intending to interact with.

The top frame is also the System app. All apps and their frames are children of the System app. Our new Marionette session starts in the System frame but to start the test we'll need to find and switch into the home screen.

To find the iFrame, we need to identify it somehow. As Marionette is based on the WebDriver API, it uses the same strategies to locate elements, so we can easily use any of the strategies used to identify WebDriver web elements. Read more information on element location strategies.

In this case we will use the CSS Selector div.homescreen iframe to select the homescreen iFrame; the find_element() function takes this as its second argument, the first argument being a definition of what selection mechanism is being used to perform the find. We'll then store this result in a variable and run the switch_to_frame() function with that as the argument. Try the following two commands now:

# Switch context to the homescreen iframe and tap on the Contacts app icon
home_frame = marionette.find_element('css selector', 'div.homescreen iframe')
marionette.switch_to_frame(home_frame)

Note: For further reading and diagrams describing switching frames, please read Working with iFrames.

Opening an application

OK. Now we’re in the Homescreen app we can target icons and tap on them using the find_element() function, in combination with the tap() function.

contacts_icon = marionette.find_element('xpath', "//div[@class='icon']//span[contains(text(),'Contacts')]")
contacts_icon.tap()

If that’s all gone right then you should now have seen the Contacts app open, but we still need to switch into the Contacts app frame in order to interact with it, like we did with the Homescreen earlier:

# First, we need to switch context back to the System frame
marionette.switch_to_frame()
 
# Now, switch context to the contacts app frame
contacts_frame = marionette.find_element('css selector', "iframe[data-url*='contacts']")
marionette.switch_to_frame(contacts_frame)

Switch to frame should return True. If it did, then great  this means we are inside the contacts app context and ready to start using it.

Manipulating the app

In the next step we’ll perform a typical test task — creating a new contact, entering a name into it, and saving it. First, we'll tap the add contact button:

# Tap [+] to add a new Contact
marionette.find_element('id', 'add-contact-button').tap()

Now let’s add the contact's name using the next two commands (send_keys() is used to insert a value into an element):

marionette.find_element('id', 'givenName').send_keys('Foo')
# Add the contact's surname
marionette.find_element('id', 'familyName').send_keys('Bar')

Now let’s tap the Done button to save the Contact:

marionette.find_element('id', 'save-button').tap()

Now you should see a new contact entered inside the Contacts app. If so, great!

Note: If you don't, reset or kill the Contacts app and navigate Firefox OS back to the Homescreen and try running the task again.

Closing your Marionette session

Finally, you should finish your Marionette session by issuing the following command:

marionette.delete_session()

That worked pretty well, but you can’t go typing into a Python console each time you want to run a test. In Part 3, we’ll compile this script into a Python file which we can reuse each time we want to run the test. We’ll also add an assertion so that we can distinguish whether the test has passed or failed.

Note: When writing Marionette commands, you'll certainly notice that accessing the underlying HTML structure of the app is vitally important to figure out the locators you need. Part 7: Writing your own tests offers some useful resources to help you with this.

 

Document Tags and Contributors

 Contributors to this page: chrisdavidmills, __Vinz__, zac_c
 Last updated by: chrisdavidmills,