mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-10-25 22:28:27 +00:00
309 lines
12 KiB
Python
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)
|