Index: chrome/test/remoting/install_and_launch_app.py |
diff --git a/chrome/test/remoting/install_and_launch_app.py b/chrome/test/remoting/install_and_launch_app.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..5a120ad4b95beb1c3af042c1e7a5709f49e7a14d |
--- /dev/null |
+++ b/chrome/test/remoting/install_and_launch_app.py |
@@ -0,0 +1,206 @@ |
+#!/usr/bin/python |
+# Copyright 2014 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""A Chromedriver smoke-test that installs and launches a web-app. |
+ |
+ Args: |
+ driver_dir: Location of Chromedriver binary on local machine. |
+ profile_dir: A user-data-dir containing login token for the app-user. |
+ app_id: App ID of web-app in Chrome web-store. |
+ app_window_title: The title of the window that should come up on app launch. |
+ |
+ TODO(anandc): Reduce the # of parameters required from the command-line. |
+ Maybe read from a JSON file. Also, map appID to expected app window title. |
+ |
+ This script navigates to the app-detail page on Chrome Web Store for the |
+ specified app-id. From there, it then installs the app and launches it. It |
+ then checks if the resulting new window has the expected title. |
+""" |
+ |
+import argparse |
+import os |
+import shutil |
+import tempfile |
+import time |
+ |
+from selenium import webdriver |
+from selenium.webdriver.chrome.options import Options |
+ |
+CWS_URL = 'https://chrome.google.com/webstore/detail' |
+WEBSTORE_BUTTON_LABEL = 'webstore-test-button-label' |
+FREE_BUTTON_XPATH = ( |
+ '//div[contains(@class, \"%s\") and text() = \"Free\"]' % |
+ (WEBSTORE_BUTTON_LABEL)) |
+LAUNCH_BUTTON_XPATH = ( |
+ '//div[contains(@class, \"%s\") and text() = \"Launch app\"]' % |
+ (WEBSTORE_BUTTON_LABEL)) |
+WAIT_TIME = 2 |
+ |
+ |
+def CreateTempProfileDir(source_dir): |
+ """Creates a temporary profile directory, for use by the test. |
+ |
+ This avoids modifying the input user-data-dir by actions that the test |
+ performs. |
+ |
+ Args: |
+ source_dir: The directory to copy and place in a temp folder. |
+ |
+ Returns: |
+ tmp_dir: Name of the temporary folder that was created. |
+ profile_dir: Name of the profile-dir under the tmp_dir. |
+ """ |
+ |
+ tmp_dir = tempfile.mkdtemp() |
+ print 'Created folder %s' % (tmp_dir) |
+ profile_dir = os.path.join(tmp_dir, 'testuser') |
+ # Copy over previous created profile for this execution of Chrome Driver. |
+ shutil.copytree(source_dir, profile_dir) |
+ return tmp_dir, profile_dir |
+ |
+ |
+def ParseCmdLineArgs(): |
+ """Parses command line arguments and returns them. |
+ |
+ Returns: |
+ args: Parse command line arguments. |
+ """ |
+ parser = argparse.ArgumentParser() |
+ parser.add_argument( |
+ '-d', '--driver_dir', required=True, |
+ help='path to folder where Chromedriver has been installed.') |
+ parser.add_argument( |
+ '-p', '--profile_dir', required=True, |
+ help='path to user-data-dir with trusted-tester signed in.') |
+ parser.add_argument( |
+ '-a', '--app_id', required=True, |
+ help='app-id of web-store app being tested.') |
+ parser.add_argument( |
+ '-e', '--app_window_title', required=True, |
+ help='Title of the app window that we expect to come up.') |
+ |
+ # Use input json file if specified on command line. |
+ args = parser.parse_args() |
+ return args |
+ |
+ |
+def GetLinkAndWait(driver, link_to_get): |
+ """Navigates to the specified link. |
+ |
+ Args: |
+ driver: Active window for this Chromedriver instance. |
+ link_to_get: URL of the destination. |
+ """ |
+ driver.get(link_to_get) |
+ # TODO(anandc): Is there any event or state we could wait on? For now, |
+ # we have hard-coded sleeps. |
+ time.sleep(WAIT_TIME) |
+ |
+ |
+def ClickAndWait(driver, button_xpath): |
+ """Clicks button at the specified XPath of the current document. |
+ |
+ Args: |
+ driver: Active window for this Chromedriver instance. |
+ button_xpath: XPath in this document to button we want to click. |
+ """ |
+ button = driver.find_element_by_xpath(button_xpath) |
+ button.click() |
+ time.sleep(WAIT_TIME) |
+ |
+ |
+def WindowWithTitleExists(driver, title): |
+ """Verifies if one of the open windows has the specified title. |
+ |
+ Args: |
+ driver: Active window for this Chromedriver instance. |
+ title: Title of the window we are looking for. |
+ |
+ Returns: |
+ True if an open window in this session with the specified title was found. |
+ False otherwise. |
+ """ |
+ for handle in driver.window_handles: |
+ driver.switch_to_window(handle) |
+ if driver.title == title: |
+ return True |
+ return False |
+ |
+ |
+def main(): |
+ |
+ args = ParseCmdLineArgs() |
+ |
+ org_profile_dir = args.profile_dir |
+ print 'Creating temp-dir using profile-dir %s' % org_profile_dir |
+ tmp_dir, profile_dir = CreateTempProfileDir(org_profile_dir) |
+ |
+ options = Options() |
+ options.add_argument('--user-data-dir=' + profile_dir) |
+ # Suppress the confirmation dialog that comes up. |
+ # With M39, this flag will no longer work. See https://crbug/357774. |
+ # TODO(anandc): Work with a profile-dir that already has extension downloaded, |
+ # and also add support for loading extension from a local directory. |
+ options.add_argument('--apps-gallery-install-auto-confirm-for-tests=accept') |
+ driver = webdriver.Chrome(args.driver_dir, chrome_options=options) |
+ |
+ try: |
+ |
+ chrome_apps_link = 'chrome://apps' |
+ cws_app_detail_link = '%s/%s' % (CWS_URL, args.app_id) |
+ |
+ # Navigate to chrome:apps first. |
+ # TODO(anandc): Add check to make sure the app we are testing isn't already |
+ # added for this user. |
+ GetLinkAndWait(driver, chrome_apps_link) |
+ |
+ # Navigate to the app detail page at the Chrome Web Store. |
+ GetLinkAndWait(driver, cws_app_detail_link) |
+ # Get the page again, to get all controls. This seems to be a bug, either |
+ # in ChromeDriver, or the app-page. Without this additional GET, we don't |
+ # get all controls. Even sleeping for 5 seconds doesn't suffice. |
+ # TODO(anandc): Investigate why the page doesn't work with just 1 call. |
+ GetLinkAndWait(driver, cws_app_detail_link) |
+ |
+ # Install the app by clicking the button that says "Free". |
+ ClickAndWait(driver, FREE_BUTTON_XPATH) |
+ |
+ # We should now be at a new tab. Get its handle. |
+ current_tab = driver.window_handles[-1] |
+ # And switch to it. |
+ driver.switch_to_window(current_tab) |
+ |
+ # From this new tab, go to Chrome Apps |
+ # TODO(anandc): Add check to make sure the app we are testing is now added. |
+ GetLinkAndWait(driver, chrome_apps_link) |
+ |
+ # Back to the app detail page. |
+ GetLinkAndWait(driver, cws_app_detail_link) |
+ # Again, do this twice, for reasons noted above. |
+ GetLinkAndWait(driver, cws_app_detail_link) |
+ |
+ # Click to launch the newly installed app. |
+ ClickAndWait(driver, LAUNCH_BUTTON_XPATH) |
+ |
+ # For now, make sure the "connecting" dialog comes up. |
+ # TODO(anandc): Add more validation; ideally, wait for the separate app |
+ # window to appear. |
+ if WindowWithTitleExists(driver, args.app_window_title): |
+ print 'Web-App %s launched successfully.' % args.app_window_title |
+ else: |
+ print 'Web-app %s did not launch successfully.' % args.app_window_title |
+ |
+ except Exception, e: |
+ raise e |
+ finally: |
+ # Cleanup. |
+ print 'Deleting %s' % tmp_dir |
+ shutil.rmtree(profile_dir) |
+ os.rmdir(tmp_dir) |
+ driver.quit() |
+ |
+ |
+if __name__ == '__main__': |
+ main() |