Bug 804515 - Add screen orientation commands to Marionette

setScreenOrientation allows for a subset of the permitted orientation
change values that screen.mozLockOrientation can take.  Specifically
portrait, landscape, portrait-primary, landscape-primary,
portrait-secondary, landscape-secondary.

Due to W3C bug 23950 both error replies use the non-descriptive 500
status code.  I've filed bug 945734 about this.
---
 testing/marionette/client/marionette/marionette.py | 47 +++++++++--
 .../tests/unit/test_screen_orientation.py          | 90 ++++++++++++++++++++++
 .../client/marionette/tests/unit/unit-tests.ini    |  2 +
 testing/marionette/marionette-server.js            | 50 +++++++++++-
 4 files changed, 183 insertions(+), 6 deletions(-)
 create mode 100644 testing/marionette/client/marionette/tests/unit/test_screen_orientation.py
This commit is contained in:
Andreas Tolfsen 2013-12-17 11:01:29 -05:00
parent 7080a66dc2
commit 85a0a4f200
4 changed files with 183 additions and 6 deletions

View File

@ -9,13 +9,14 @@ import sys
import time import time
import traceback import traceback
from client import MarionetteClient
from application_cache import ApplicationCache from application_cache import ApplicationCache
from keys import Keys from client import MarionetteClient
from errors import *
from emulator import Emulator from emulator import Emulator
import geckoinstance from emulator_screen import EmulatorScreen
from errors import *
from keys import Keys
import geckoinstance
class HTMLElement(object): class HTMLElement(object):
""" """
@ -421,6 +422,12 @@ class Marionette(object):
TIMEOUT_SEARCH = 'implicit' TIMEOUT_SEARCH = 'implicit'
TIMEOUT_SCRIPT = 'script' TIMEOUT_SCRIPT = 'script'
TIMEOUT_PAGE = 'page load' TIMEOUT_PAGE = 'page load'
SCREEN_ORIENTATIONS = {"portrait": EmulatorScreen.SO_PORTRAIT_PRIMARY,
"landscape": EmulatorScreen.SO_LANDSCAPE_PRIMARY,
"portrait-primary": EmulatorScreen.SO_PORTRAIT_PRIMARY,
"landscape-primary": EmulatorScreen.SO_LANDSCAPE_PRIMARY,
"portrait-secondary": EmulatorScreen.SO_PORTRAIT_SECONDARY,
"landscape-secondary": EmulatorScreen.SO_LANDSCAPE_SECONDARY}
def __init__(self, host='localhost', port=2828, app=None, app_args=None, bin=None, def __init__(self, host='localhost', port=2828, app=None, app_args=None, bin=None,
profile=None, emulator=None, sdcard=None, emulatorBinary=None, profile=None, emulator=None, sdcard=None, emulatorBinary=None,
@ -592,7 +599,7 @@ class Marionette(object):
status = response['error'].get('status', 500) status = response['error'].get('status', 500)
message = response['error'].get('message') message = response['error'].get('message')
stacktrace = response['error'].get('stacktrace') stacktrace = response['error'].get('stacktrace')
# status numbers come from # status numbers come from
# http://code.google.com/p/selenium/wiki/JsonWireProtocol#Response_Status_Codes # http://code.google.com/p/selenium/wiki/JsonWireProtocol#Response_Status_Codes
if status == ErrorCodes.NO_SUCH_ELEMENT: if status == ErrorCodes.NO_SUCH_ELEMENT:
raise NoSuchElementException(message=message, status=status, stacktrace=stacktrace) raise NoSuchElementException(message=message, status=status, stacktrace=stacktrace)
@ -1280,3 +1287,33 @@ class Marionette(object):
if highlights is not None: if highlights is not None:
lights = [highlight.id for highlight in highlights if highlights] lights = [highlight.id for highlight in highlights if highlights]
return self._send_message("screenShot", 'value', id=element, highlights=lights) return self._send_message("screenShot", 'value', id=element, highlights=lights)
@property
def orientation(self):
"""Get the current browser orientation.
Will return one of the valid primary orientation values
portrait-primary, landscape-primary, portrait-secondary, or
landscape-secondary.
"""
return self._send_message("getScreenOrientation", "value")
def set_orientation(self, orientation):
"""Set the current browser orientation.
The supplied orientation should be given as one of the valid
orientation values. If the orientation is unknown, an error
will be raised.
Valid orientations are "portrait" and "landscape", which fall
back to "portrait-primary" and "landscape-primary"
respectively, and "portrait-secondary" as well as
"landscape-secondary".
:param orientation: The orientation to lock the screen in.
"""
self._send_message("setScreenOrientation", "ok", orientation=orientation)
if self.emulator:
self.emulator.screen.orientation = self.SCREEN_ORIENTATIONS[orientation.lower()]

View File

@ -0,0 +1,90 @@
# -*- fill-column: 100; comment-column: 100; -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from emulator_screen import EmulatorScreen
from marionette import MarionetteException
from marionette_test import MarionetteTestCase
default_orientation = "portrait-primary"
unknown_orientation = "Unknown screen orientation: %s"
class TestScreenOrientation(MarionetteTestCase):
def tearDown(self):
self.marionette.set_orientation(default_orientation)
self.assertEqual(self.marionette.orientation, default_orientation, "invalid state")
super(MarionetteTestCase, self).tearDown()
def test_set_orientation_to_portrait_primary(self):
self.marionette.set_orientation("portrait-primary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "portrait-primary")
if self.marionette.emulator:
emulator_orientation = self.marionette.emulator.screen.orientation
self.assertEqual(emulator_orientation, EmulatorScreen.SO_PORTRAIT_PRIMARY)
def test_set_orientation_to_landscape_primary(self):
self.marionette.set_orientation("landscape-primary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-primary")
if self.marionette.emulator:
emulator_orientation = self.marionette.emulator.screen.orientation
self.assertEqual(emulator_orientation, EmulatorScreen.SO_LANDSCAPE_PRIMARY)
def test_set_orientation_to_portrait_secondary(self):
self.marionette.set_orientation("portrait-secondary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "portrait-secondary")
if self.marionette.emulator:
emulator_orientation = self.marionette.emulator.screen.orientation
self.assertEqual(emulator_orientation, EmulatorScreen.SO_PORTRAIT_SECONDARY)
def test_set_orientation_to_landscape_secondary(self):
self.marionette.set_orientation("landscape-secondary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-secondary")
if self.marionette.emulator:
emulator_orientation = self.marionette.emulator.screen.orientation
self.assertEqual(emulator_orientation, EmulatorScreen.SO_LANDSCAPE_SECONDARY)
def test_set_orientation_to_shorthand_portrait(self):
# Set orientation to something other than portrait-primary first, since the default is
# portrait-primary.
self.marionette.set_orientation("landscape-primary")
self.assertEqual(self.marionette.orientation, "landscape-primary", "invalid state")
self.marionette.set_orientation("portrait")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "portrait-primary")
if self.marionette.emulator:
emulator_orientation = self.marionette.emulator.screen.orientation
self.assertEqual(emulator_orientation, EmulatorScreen.SO_PORTRAIT_PRIMARY)
def test_set_orientation_to_shorthand_landscape(self):
self.marionette.set_orientation("landscape")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-primary")
if self.marionette.emulator:
emulator_orientation = self.marionette.emulator.screen.orientation
self.assertEqual(emulator_orientation, EmulatorScreen.SO_LANDSCAPE_PRIMARY)
def test_set_orientation_with_mixed_casing(self):
self.marionette.set_orientation("lAnDsCaPe")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-primary")
def test_set_invalid_orientation(self):
with self.assertRaisesRegexp(MarionetteException, unknown_orientation % "cheese"):
self.marionette.set_orientation("cheese")
def test_set_null_orientation(self):
with self.assertRaisesRegexp(MarionetteException, unknown_orientation % "null"):
self.marionette.set_orientation(None)

View File

@ -97,3 +97,5 @@ b2g = false
[test_getactiveframe_oop.py] [test_getactiveframe_oop.py]
[test_submit.py] [test_submit.py]
[test_chrome_async_finish.js] [test_chrome_async_finish.js]
[test_screen_orientation.py]
browser = false

View File

@ -2161,6 +2161,52 @@ MarionetteServerConnection.prototype = {
this.command_id); this.command_id);
}, },
/**
* Get the current browser orientation.
*
* Will return one of the valid primary orientation values
* portrait-primary, landscape-primary, portrait-secondary, or
* landscape-secondary.
*/
getScreenOrientation: function MDA_getScreenOrientation(aRequest) {
this.command_id = this.getCommandId();
let curWindow = this.getCurrentWindow();
let or = curWindow.screen.mozOrientation;
this.sendResponse(or, this.command_id);
},
/**
* Set the current browser orientation.
*
* The supplied orientation should be given as one of the valid
* orientation values. If the orientation is unknown, an error will
* be raised.
*
* Valid orientations are "portrait" and "landscape", which fall
* back to "portrait-primary" and "landscape-primary" respectively,
* and "portrait-secondary" as well as "landscape-secondary".
*/
setScreenOrientation: function MDA_setScreenOrientation(aRequest) {
const ors = ["portrait", "landscape",
"portrait-primary", "landscape-primary",
"portrait-secondary", "landscape-secondary"];
this.command_id = this.getCommandId();
let or = String(aRequest.parameters.orientation);
let mozOr = or.toLowerCase();
if (ors.indexOf(mozOr) < 0) {
this.sendError("Unknown screen orientation: " + or, 500, null, this.command_id);
return;
}
let curWindow = this.getCurrentWindow();
if (!curWindow.screen.mozLockOrientation(mozOr)) {
this.sendError("Unable to set screen orientation: " + or, 500, null, this.command_id);
}
this.sendOk(this.command_id);
},
/** /**
* Helper function to convert an outerWindowID into a UID that Marionette * Helper function to convert an outerWindowID into a UID that Marionette
* tracks. * tracks.
@ -2338,7 +2384,9 @@ MarionetteServerConnection.prototype.requestTypes = {
"getAllCookies": MarionetteServerConnection.prototype.getAllCookies, "getAllCookies": MarionetteServerConnection.prototype.getAllCookies,
"deleteAllCookies": MarionetteServerConnection.prototype.deleteAllCookies, "deleteAllCookies": MarionetteServerConnection.prototype.deleteAllCookies,
"deleteCookie": MarionetteServerConnection.prototype.deleteCookie, "deleteCookie": MarionetteServerConnection.prototype.deleteCookie,
"getActiveElement": MarionetteServerConnection.prototype.getActiveElement "getActiveElement": MarionetteServerConnection.prototype.getActiveElement,
"getScreenOrientation": MarionetteServerConnection.prototype.getScreenOrientation,
"setScreenOrientation": MarionetteServerConnection.prototype.setScreenOrientation
}; };
/** /**