OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """A Chromedriver smoke-test that installs and launches a web-app. | |
7 | |
8 Args: | |
9 driver_dir: Location of Chromedriver binary on local machine. | |
10 profile_dir: A user-data-dir containing login token for the app user. | |
11 app_id: App ID of web-app in Chrome web-store. | |
12 app_window_title: The title of the window that should come up on app launch. | |
13 | |
14 TODO(anandc): Reduce the # of parameters required from the command-line. | |
15 Maybe read from a JSON file. Also, map appID to expected app window title. | |
16 | |
17 This script navigates to the app-detail page on Chrome Web Store for the | |
18 specified app-id. From there, it then installs the app and launches it. It | |
19 then checks if the resulting new window has the expected title. | |
20 | |
21 """ | |
22 | |
23 import argparse | |
24 import os | |
25 import shutil | |
26 import tempfile | |
27 import time | |
28 | |
29 from selenium import webdriver | |
30 from selenium.webdriver.chrome.options import Options | |
31 | |
32 CWS_URL = 'https://chrome.google.com/webstore/detail' | |
33 WEBSTORE_BUTTON_LABEL = 'webstore-test-button-label' | |
34 FREE_BUTTON_XPATH = ( | |
35 '//div[contains(@class, \"%s\") and text() = \"Free\"]' % | |
36 (WEBSTORE_BUTTON_LABEL)) | |
37 LAUNCH_BUTTON_XPATH = ( | |
38 '//div[contains(@class, \"%s\") and text() = \"Launch app\"]' % | |
39 (WEBSTORE_BUTTON_LABEL)) | |
40 | |
41 | |
42 def CreateTempProfileDir(source_dir): | |
43 """Creates a temporary profile directory, for use by the test. | |
44 | |
45 This avoids modifying the input user-data-dir by actions that the test | |
46 performs. | |
47 | |
48 Args: | |
49 source_dir: The directory to copy and place in a temp folder. | |
50 | |
51 Returns: | |
52 tmp_dir: Name of the temporary folder that was created. | |
53 profile_dir: Name of the profile-dir under the tmp_dir. | |
54 """ | |
55 | |
56 tmp_dir = tempfile.mkdtemp() | |
57 print 'Created folder %s' % (tmp_dir) | |
58 profile_dir = os.path.join(tmp_dir, 'testuser') | |
59 # Copy over previous created profile for this execution of Chrome Driver. | |
60 shutil.copytree(source_dir, profile_dir) | |
61 return tmp_dir, profile_dir | |
62 | |
63 | |
64 def ParseCmdLineArgs(): | |
65 """Parses command line arguments and returns them. | |
66 | |
67 Returns: | |
68 args: Parse command line arguments. | |
69 """ | |
70 parser = argparse.ArgumentParser() | |
71 parser.add_argument( | |
72 '-d', '--driver_dir', required=True, | |
73 help='path to folder where Chromedriver has been installed.') | |
74 parser.add_argument( | |
75 '-p', '--profile_dir', required=True, | |
76 help='path to user-data-dir with trusted-tester signed in.') | |
77 parser.add_argument( | |
78 '-a', '--app_id', required=True, | |
79 help='app-id of web-store app being tested.') | |
80 parser.add_argument( | |
81 '-e', '--app_window_title', required=True, | |
82 help='Title of the app window that we expect to come up.') | |
83 | |
84 # Use input json file if specified on command line. | |
85 args = parser.parse_args() | |
86 return args | |
87 | |
88 | |
89 def main(): | |
90 | |
91 args = ParseCmdLineArgs() | |
92 | |
93 org_profile_dir = args.profile_dir | |
94 print 'Creating temp-dir using profile-dir %s' % org_profile_dir | |
95 tmp_dir, profile_dir = CreateTempProfileDir(org_profile_dir) | |
96 | |
97 options = Options() | |
98 options.add_argument('--user-data-dir=' + profile_dir) | |
99 # Suppress the confirmation dialog that comes up. | |
100 # With M39, this flag will no longer work. See https://crbug/357774. | |
101 # TODO(anandc): Work with a profile-dir that already has extension downloaded, | |
102 # and also add support for loading extension from a local directory. | |
103 options.add_argument('--apps-gallery-install-auto-confirm-for-tests=accept') | |
104 driver = webdriver.Chrome(args.driver_dir, chrome_options=options) | |
105 | |
106 try: | |
107 | |
108 # Navigate to chrome:apps first. | |
109 # TODO(anandc): add check to make sure the app we are testing isn't already | |
garykac
2014/09/18 23:33:16
nit: "Add"
(and "Is" below)
anandc
2014/09/19 21:05:31
Done.
| |
110 # added for this user. | |
111 chrome_apps_link = 'chrome://apps' | |
112 driver.get(chrome_apps_link) | |
113 # TODO(anandc): is there any event or state we could wait on? For now, | |
114 # we have hard-coded sleeps. | |
115 time.sleep(2) | |
116 | |
117 cws_app_detail_link = '%s/%s' % (CWS_URL, args.app_id) | |
118 # Navigate to the app page at Chrome Web Store. | |
119 driver.get(cws_app_detail_link) | |
120 # Get the page again, to get all controls. This seems to be a bug, either | |
121 # in ChromeDriver, or the app-page. Without this additional GET, we don't | |
122 # get all controls. Even sleeping for 5 seconds doesn't suffice. | |
123 # TODO(anandc): Investigate why the page doesn't work with just 1 call. | |
124 driver.get(cws_app_detail_link) | |
125 time.sleep(2) | |
garykac
2014/09/18 23:33:16
Not sure if it's worth doing, but these time.sleep
anandc
2014/09/19 21:05:31
Done.
| |
126 | |
127 # Install the app by clicking the button that says "Free". | |
128 free_button = driver.find_element_by_xpath(FREE_BUTTON_XPATH) | |
129 free_button.click() | |
130 time.sleep(2) | |
131 | |
132 # We should now be at a new tab; switch to it. | |
133 current_tab = driver.window_handles[-1] | |
134 driver.switch_to_window(current_tab) | |
135 # Go to Chrome Apps | |
136 # TODO(anandc): add check to make sure the app we are testing is now added. | |
137 driver.get(chrome_apps_link) | |
138 # Now that the app has been installed, go back to its details page, | |
139 # and launch it. (2 GET calls again, once is not enough; see not above.) | |
garykac
2014/09/18 23:33:16
The code will be a bit easier to follow if you hav
anandc
2014/09/19 21:05:32
Makes sense. Thanks.
Done, with a slight differe
| |
140 driver.get(cws_app_detail_link) | |
141 driver.get(cws_app_detail_link) | |
142 time.sleep(2) | |
143 | |
144 launch_button = driver.find_element_by_xpath(LAUNCH_BUTTON_XPATH) | |
garykac
2014/09/18 23:33:16
This chunk can be re-used as well:
def click_wait
anandc
2014/09/19 21:05:32
Done.
| |
145 launch_button.click() | |
146 time.sleep(2) | |
147 | |
148 # For now, make sure the "connecting" dialog comes up. | |
149 # TODO(anandc): add more validation; ideally, wait for the separate app | |
150 # window to appear. | |
151 success = False | |
152 for handle in driver.window_handles: | |
153 driver.switch_to_window(handle) | |
154 if driver.title == args.app_window_title: | |
155 success = True | |
156 print 'Webapp launched successfully.' | |
157 break | |
158 | |
159 if not success: | |
160 print 'Webapp did not launch successfully.' | |
161 | |
162 except Exception, e: | |
163 raise e | |
164 finally: | |
165 # Cleanup | |
166 print 'Deleting %s' % tmp_dir | |
167 shutil.rmtree(profile_dir) | |
168 os.rmdir(tmp_dir) | |
169 driver.quit() | |
170 | |
171 | |
172 if __name__ == '__main__': | |
173 main() | |
OLD | NEW |