blob: bb86d6c8463a79432516e67e6f4cdf0d4618085c [file] [log] [blame]
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import os
import json
import time
import common
from autotest_lib.client.bin import test
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chromedriver
from autotest_lib.client.cros import httpd
class desktopui_SonicExtension(test.test):
"""Test loading the sonic extension through chromedriver."""
version = 1
cast_delay = 20
dep = 'sonic_extension'
def _install_sonic_extension(self):
dep_dir = os.path.join(self.autodir, 'deps', self.dep)
logging.info('Installing sonic extension into %s', dep_dir)
self.job.install_pkg(self.dep, 'dep', dep_dir)
return dep_dir
def _check_manifest(self, extension_path):
"""Checks the manifest for a public key.
The sonic extension is an autotest dependency and will get
installed through install_pkg as a component extension (with
a public key). Any other method of installation is supported
too, as long as it has a public key.
@param extension_path: A path to the directory of the extension
that contains a manifest.json.
@raises TestError: If the extension doesn't have a public key.
"""
manifest_json_file = os.path.join(extension_path, 'manifest.json')
with open(manifest_json_file, 'r') as f:
manifest_json = json.loads(f.read())
if not manifest_json.get('key'):
raise error.TestError('Not a component extension, cannot '
'proceed with sonic test')
def tab_cast(self, driver, chromecast_ip, extension_id):
"""Tab cast through the extension.
@param driver: A chromedriver instance that has the chromecast
extension loaded.
@param chromecast_ip: The ip of the chromecast device to cast to.
@param extension_id: Id of the extension to use.
"""
extension_url = 'chrome-extension://%s' % extension_id
driver.get('%s/%s' % (extension_url, self._test_utils_page))
if driver.title != self._test_utils_title:
raise error.TestError('Getting title failed, got title: %s'
% driver.title)
driver.find_element_by_id('receiverIpAddress').send_keys(
chromecast_ip)
logging.info('Attempting to cast %s', self._test_url)
driver.find_element_by_id('urlToOpen').send_keys(self._test_url)
driver.find_element_by_id('mirrorUrl').click()
def initialize(self, extension_dir=None, live=False):
"""Initialize the test.
@param extension_dir: Directory of a custom extension.
If one isn't supplied, the latest ToT extension is
downloaded and loaded into chromedriver.
@param live: Use a live url if True. Start a test server
and server a hello world page if False.
"""
super(desktopui_SonicExtension, self).initialize()
if not extension_dir:
extension_path = self._install_sonic_extension()
else:
extension_path = os.path.join(self.autodir, 'tests',
'desktopui_SonicExtension',
extension_dir)
if not os.path.exists(extension_path):
raise error.TestError('Failed to install sonic extension.')
self._check_manifest(extension_path)
self._extension_path = extension_path
self._test_utils_page = 'e2e_test_utils.html'
self._test_utils_title = 'Google Cast extension E2E test utilities'
self._whitelist_id = 'enhhojjnijigcajfphajepfemndkmdlo'
if live:
self._test_url = 'http://www.google.com'
self._test_server = None
else:
self._test_url = 'http://localhost:8000/hello.html'
self._test_server = httpd.HTTPListener(8000, docroot=self.bindir)
self._test_server.run()
def cleanup(self):
"""Clean up the test environment, e.g., stop local http server."""
if self._test_server:
self._test_server.stop()
super(desktopui_SonicExtension, self).cleanup()
def _close_popups(self, driver):
"""Close any popup windows the extension might open by default.
Since we're going to handle the extension ourselves all we need is
the main browser window with a single tab. The safest way to handle
the popup however, is to close the currently active tab, so we don't
mess with webdrivers ui debugger.
@param driver: Chromedriver instance.
@raises WebDriverException: If you close the tab associated with
the ui debugger.
"""
# TODO: There are several, albeit hacky ways, to handle this popup
# that might need to change with different versions of the extension
# until the core issue is resolved. See crbug.com/338399.
if len(driver.window_handles) > 1:
driver.close()
driver.switch_to_window(driver.window_handles[0])
def run_once(self, chromecast_ip):
"""Run the test code."""
# TODO: When we've cloned the sonic test repo get these from their
# test config files.
logging.info('Starting sonic client test.')
kwargs = {
'extension_paths' : [self._extension_path],
'is_component' : True,
'extra_chrome_flags': ['--no-proxy-server', '--start-maximized',
'--disable-web-security',
'--enable-experimental-extension-apis',
'--enable-logging=stderr', '--v=2',
('--whitelisted-extension-id=%s' %
self._whitelist_id)],
}
with chromedriver.chromedriver(**kwargs) as chromedriver_instance:
driver = chromedriver_instance.driver
self._close_popups(driver)
extension = chromedriver_instance.get_extension(
self._extension_path)
logging.info('Starting tabcast to extension: %s',
extension.extension_id)
self.tab_cast(driver, chromecast_ip, extension.extension_id)
time.sleep(self.cast_delay)
screenshot_file = 'sonic_screenshot'
utils.take_screenshot(self.resultsdir, screenshot_file)
logging.info('Screenshot of cast extension saved to %s',
os.path.join(self.resultsdir, screenshot_file))