tenfourfox/browser/extensions/loop/test/functional/test_1_browser_call.py
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

309 lines
12 KiB
Python

from marionette_driver.by import By
from marionette_driver.errors import NoSuchElementException, StaleElementException
# noinspection PyUnresolvedReferences
from marionette_driver import Wait
from marionette import MarionetteTestCase
import os
import sys
import time
import urlparse
sys.path.insert(1, os.path.dirname(os.path.abspath(__file__)))
import pyperclip
from serversetup import LoopTestServers
from config import FIREFOX_PREFERENCES
class Test1BrowserCall(MarionetteTestCase):
# XXX Move this to setup class so it doesn't restart the server
# after every test.
def setUp(self):
# start server
self.loop_test_servers = LoopTestServers()
MarionetteTestCase.setUp(self)
# Unfortunately, enforcing preferences currently comes with the side
# effect of launching and restarting the browser before running the
# real functional tests. Bug 1048554 has been filed to track this.
self.marionette.enforce_gecko_prefs(FIREFOX_PREFERENCES)
# this is browser chrome, kids, not the content window just yet
self.marionette.set_context("chrome")
# taken from https://github.com/mozilla-b2g/gaia/blob/master/tests/python/gaia-ui-tests/gaiatest/gaia_test.py#L858
# XXX factor out into utility object for use by other tests
def wait_for_element_displayed(self, by, locator, timeout=None):
Wait(self.marionette, timeout,
ignored_exceptions=[NoSuchElementException, StaleElementException])\
.until(lambda m: m.find_element(by, locator).is_displayed())
return self.marionette.find_element(by, locator)
def wait_for_subelement_displayed(self, parent, by, locator, timeout=None):
Wait(self.marionette, timeout,
ignored_exceptions=[NoSuchElementException, StaleElementException])\
.until(lambda m: parent.find_element(by, locator).is_displayed())
return parent.find_element(by, locator)
# XXX workaround for Marionette bug 1094246
def wait_for_element_exists(self, by, locator, timeout=None):
Wait(self.marionette, timeout,
ignored_exceptions=[NoSuchElementException, StaleElementException]) \
.until(lambda m: m.find_element(by, locator))
return self.marionette.find_element(by, locator)
def wait_for_element_enabled(self, element, timeout=10):
Wait(self.marionette, timeout) \
.until(lambda e: element.is_enabled(),
message="Timed out waiting for element to be enabled")
def wait_for_element_attribute_to_be_false(self, element, attribute, timeout=10):
Wait(self.marionette, timeout) \
.until(lambda e: element.get_attribute(attribute) == "false",
message="Timeout out waiting for " + attribute + " to be false")
def switch_to_panel(self):
button = self.marionette.find_element(By.ID, "loop-button")
# click the element
button.click()
# switch to the frame
frame = self.marionette.find_element(By.ID, "loop-panel-iframe")
self.marionette.switch_to_frame(frame)
def switch_to_chatbox(self):
self.marionette.set_context("chrome")
self.marionette.switch_to_frame()
# Added time lapse to allow for DOM to catch up
time.sleep(2)
# XXX should be using wait_for_element_displayed, but need to wait
# for Marionette bug 1094246 to be fixed.
chatbox = self.wait_for_element_exists(By.TAG_NAME, 'chatbox')
script = ("return document.getAnonymousElementByAttribute("
"arguments[0], 'anonid', 'content');")
frame = self.marionette.execute_script(script, [chatbox])
self.marionette.switch_to_frame(frame)
def switch_to_standalone(self):
self.marionette.set_context("content")
def local_start_a_conversation(self):
button = self.wait_for_element_displayed(By.CSS_SELECTOR, ".new-room-view .btn-info")
self.wait_for_element_enabled(button, 120)
button.click()
def local_check_room_self_video(self):
self.switch_to_chatbox()
# expect a video container on desktop side
media_container = self.wait_for_element_displayed(By.CLASS_NAME, "media-layout")
self.assertEqual(media_container.tag_name, "div", "expect a video container")
self.check_video(".local-video")
def local_get_and_verify_room_url(self):
self.switch_to_chatbox()
button = self.wait_for_element_displayed(By.CLASS_NAME, "btn-copy")
button.click()
# click the element
room_url = pyperclip.paste()
self.assertIn(urlparse.urlparse(room_url).scheme, ['http', 'https'],
"room URL returned by server: '" + room_url +
"' has invalid scheme")
return room_url
def standalone_load_and_join_room(self, url):
self.switch_to_standalone()
self.marionette.navigate(url)
# Join the room - the first time around, the tour will be displayed
# so we look for its close button.
tour_close_button = self.wait_for_element_displayed(By.CLASS_NAME,
"button-close")
tour_close_button.click()
# Assumes the standalone or the conversation window is selected first.
def check_video(self, selector):
video = self.wait_for_element_displayed(By.CSS_SELECTOR,
selector, 30)
self.wait_for_element_attribute_to_be_false(video, "paused")
self.assertEqual(video.get_attribute("ended"), "false")
def standalone_check_remote_video(self):
self.switch_to_standalone()
self.check_video(".remote-video")
def local_check_remote_video(self):
self.switch_to_chatbox()
self.check_video(".remote-video")
def send_chat_message(self, text):
"""
Sends a chat message using the current context.
:param text: The text to send.
"""
chatbox = self.wait_for_element_displayed(By.CSS_SELECTOR,
".text-chat-box > form > input")
chatbox.send_keys(text + "\n")
def check_received_message(self, expectedText):
"""
Checks a chat message has been received in the current context. The
test assumes only one chat message will be received during the tests.
:param expectedText: The expected text of the chat message.
"""
text_entry = self.wait_for_element_displayed(By.CSS_SELECTOR,
".text-chat-entry.received > p > span")
self.assertEqual(text_entry.text, expectedText,
"should have received the correct message")
def check_text_messaging(self):
"""
Checks text messaging between the generator and clicker in a bi-directional
fashion.
"""
# Send a message using the link generator.
self.switch_to_chatbox()
self.send_chat_message("test1")
# Now check the result on the link clicker.
self.switch_to_standalone()
self.check_received_message("test1")
# Then send a message using the standalone.
self.send_chat_message("test2")
# Finally check the link generator got it.
self.switch_to_chatbox()
self.check_received_message("test2")
def standalone_check_remote_screenshare(self):
self.switch_to_standalone()
self.check_video(".screen-share-video")
def remote_leave_room(self):
self.switch_to_standalone()
button = self.marionette.find_element(By.CLASS_NAME, "btn-hangup")
button.click()
self.switch_to_chatbox()
# check that the local view reverts to the preview mode
self.wait_for_element_displayed(By.CLASS_NAME, "room-invitation-content")
def local_get_chatbox_window_expr(self, expr):
"""
:expr: a sub-expression which must begin with a property of the
global content window (e.g. "location.path")
:return: the value of the given sub-expression as evaluated in the
chatbox content window
"""
self.marionette.set_context("chrome")
self.marionette.switch_to_frame()
# XXX should be using wait_for_element_displayed, but need to wait
# for Marionette bug 1094246 to be fixed.
chatbox = self.wait_for_element_exists(By.TAG_NAME, 'chatbox')
script = '''
let chatBrowser = document.getAnonymousElementByAttribute(
arguments[0], 'anonid',
'content')
// note that using wrappedJSObject waives X-ray vision, which
// has security implications, but because we trust the code
// running in the chatbox, it should be reasonably safe
let chatGlobal = chatBrowser.contentWindow.wrappedJSObject;
return chatGlobal.''' + expr
return self.marionette.execute_script(script, [chatbox])
def local_get_media_start_time(self):
return self.local_get_chatbox_window_expr(
"loop.conversation._sdkDriver._getTwoWayMediaStartTime()")
# XXX could be memoized
def local_get_media_start_time_uninitialized(self):
return self.local_get_chatbox_window_expr(
"loop.conversation._sdkDriver.CONNECTION_START_TIME_UNINITIALIZED"
)
def local_check_media_start_time_uninitialized(self):
self.assertEqual(
self.local_get_media_start_time(),
self.local_get_media_start_time_uninitialized(),
"media start time should be uninitialized before "
"link clicker enters room")
def local_check_media_start_time_initialized(self):
self.assertNotEqual(
self.local_get_media_start_time(),
self.local_get_media_start_time_uninitialized(),
"media start time should be initialized after "
"media is bidirectionally connected")
def local_check_connection_length_noted(self):
noted_calls = self.local_get_chatbox_window_expr(
"loop.conversation._sdkDriver._connectionLengthNotedCalls")
self.assertGreater(noted_calls, 0,
"OTSdkDriver._connectionLengthNotedCalls should be "
"> 0, noted_calls = " + str(noted_calls))
def test_1_browser_call(self):
self.switch_to_panel()
self.local_start_a_conversation()
# Check the self video in the conversation window
self.local_check_room_self_video()
# make sure that the media start time is not initialized
self.local_check_media_start_time_uninitialized()
room_url = self.local_get_and_verify_room_url()
# load the link clicker interface into the current content browser
self.standalone_load_and_join_room(room_url)
# Check we get the video streams
self.standalone_check_remote_video()
self.local_check_remote_video()
# Check text messaging
self.check_text_messaging()
# since bi-directional media is connected, make sure we've set
# the start time
self.local_check_media_start_time_initialized()
# Check that screenshare was automatically started
self.standalone_check_remote_screenshare()
# We hangup on the remote (standalone) side, because this also leaves
# the local chatbox with the local publishing media still connected,
# which means that the local_check_connection_length below
# verifies that the connection is noted at the time the remote media
# drops, rather than waiting until the window closes.
self.remote_leave_room()
self.local_check_connection_length_noted()
def tearDown(self):
self.loop_test_servers.shutdown()
MarionetteTestCase.tearDown(self)