Merge lp:~elopio/unity-scope-click/split_scope into lp:unity-scope-click/devel
- split_scope
- Merge into devel
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | 307 |
Merged at revision: | 318 |
Proposed branch: | lp:~elopio/unity-scope-click/split_scope |
Merge into: | lp:unity-scope-click/devel |
Diff against target: |
634 lines (+366/-124) 3 files modified
autopilot/unityclickscope/__init__.py (+128/-0) autopilot/unityclickscope/fake_servers.py (+156/-50) autopilot/unityclickscope/test_click_scope.py (+82/-74) |
To merge this branch: | bzr merge lp:~elopio/unity-scope-click/split_scope |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
dobey (community) | Approve | ||
Review via email: mp+224926@code.launchpad.net |
Commit message
Updated the autopilot tests to use the split scopes.
Updated the tests to use dobey's application.
Moved all the helpers to the unityclickscope namespace, so they can be reused by UX tests.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:301
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:301
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:301
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:302
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:304
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:304
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:305
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:305
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:307
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:307
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:307
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
dobey (dobey) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'autopilot/unityclickscope/__init__.py' | |||
2 | --- autopilot/unityclickscope/__init__.py 2013-12-28 02:13:26 +0000 | |||
3 | +++ autopilot/unityclickscope/__init__.py 2014-07-07 21:14:23 +0000 | |||
4 | @@ -0,0 +1,128 @@ | |||
5 | 1 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- | ||
6 | 2 | # | ||
7 | 3 | # Copyright (C) 2013, 2014 Canonical Ltd. | ||
8 | 4 | # | ||
9 | 5 | # This program is free software; you can redistribute it and/or modify | ||
10 | 6 | # it under the terms of the GNU General Public License version 3, as published | ||
11 | 7 | # by the Free Software Foundation. | ||
12 | 8 | # | ||
13 | 9 | # This program is distributed in the hope that it will be useful, | ||
14 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | 12 | # GNU General Public License for more details. | ||
17 | 13 | # | ||
18 | 14 | # You should have received a copy of the GNU General Public License | ||
19 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | 16 | |||
21 | 17 | import logging | ||
22 | 18 | |||
23 | 19 | import autopilot.logging | ||
24 | 20 | import ubuntuuitoolkit | ||
25 | 21 | from autopilot.introspection import dbus as autopilot_dbus | ||
26 | 22 | from testtools.matchers import Equals, MatchesAny | ||
27 | 23 | from unity8.shell.emulators import dash | ||
28 | 24 | |||
29 | 25 | |||
30 | 26 | logger = logging.getLogger(__name__) | ||
31 | 27 | |||
32 | 28 | |||
33 | 29 | class GenericScopeView(dash.DashApps): | ||
34 | 30 | |||
35 | 31 | """Autopilot helper for the generic scope view of the store.""" | ||
36 | 32 | |||
37 | 33 | # XXX We need to set an objectName to this scope, so we can put a different | ||
38 | 34 | # name to this custom proxy object class. --elopio - 2014-06-28 | ||
39 | 35 | |||
40 | 36 | def enter_search_query(self, query): | ||
41 | 37 | # TODO once http://pad.lv/1335551 is fixed, we can use the search | ||
42 | 38 | # helpers from unity. --elopio - 2014-06-28 | ||
43 | 39 | search_text_field = self._get_search_text_field() | ||
44 | 40 | search_text_field.write(query) | ||
45 | 41 | search_text_field.state.wait_for('idle') | ||
46 | 42 | |||
47 | 43 | def _get_search_text_field(self): | ||
48 | 44 | page_header = self._get_scope_item_header() | ||
49 | 45 | search_container = page_header.select_single( | ||
50 | 46 | 'QQuickItem', objectName='searchContainer') | ||
51 | 47 | search_container.state.wait_for( | ||
52 | 48 | MatchesAny(Equals('narrowActive'), Equals('active'))) | ||
53 | 49 | return search_container.select_single(ubuntuuitoolkit.TextField) | ||
54 | 50 | |||
55 | 51 | def _get_scope_item_header(self): | ||
56 | 52 | return self._get_scope_item().select_single( | ||
57 | 53 | 'PageHeader', objectName='') | ||
58 | 54 | |||
59 | 55 | def _get_scope_item(self): | ||
60 | 56 | return self.get_root_instance().select_single('ScopeItem') | ||
61 | 57 | |||
62 | 58 | @autopilot.logging.log_action(logger.info) | ||
63 | 59 | def open_preview(self, category, app_name): | ||
64 | 60 | """Open the preview of an application. | ||
65 | 61 | |||
66 | 62 | :parameter category: The name of the category where the application is. | ||
67 | 63 | :parameter app_name: The name of the application. | ||
68 | 64 | :return: The opened preview. | ||
69 | 65 | |||
70 | 66 | """ | ||
71 | 67 | category_element = self._get_category_element(category) | ||
72 | 68 | icon = category_element.select_single('AbstractButton', title=app_name) | ||
73 | 69 | self.pointing_device.click_object(icon) | ||
74 | 70 | # TODO assign an object name to this preview list view. | ||
75 | 71 | # --elopio - 2014-06-29 | ||
76 | 72 | preview_list = self._get_scope_item().wait_select_single( | ||
77 | 73 | 'PreviewListView', objectName='') | ||
78 | 74 | preview_list.x.wait_for(0) | ||
79 | 75 | return preview_list.select_single( | ||
80 | 76 | Preview, objectName='preview{}'.format(preview_list.currentIndex)) | ||
81 | 77 | |||
82 | 78 | |||
83 | 79 | class DashApps(dash.DashApps): | ||
84 | 80 | |||
85 | 81 | """Autopilot helper for the applicatios scope.""" | ||
86 | 82 | |||
87 | 83 | @autopilot.logging.log_action(logger.info) | ||
88 | 84 | def go_to_store(self): | ||
89 | 85 | """Open the applications store. | ||
90 | 86 | |||
91 | 87 | :return: The store Scope View. | ||
92 | 88 | |||
93 | 89 | """ | ||
94 | 90 | # TODO call click_scope_item once the fix for bug http://pad.lv/1335548 | ||
95 | 91 | # lands. --elopio - 2014-06-28 | ||
96 | 92 | category_element = self._get_category_element('store') | ||
97 | 93 | icon = category_element.select_single( | ||
98 | 94 | 'AbstractButton', title='Ubuntu Store') | ||
99 | 95 | self.pointing_device.click_object(icon) | ||
100 | 96 | scope_item = self.get_root_instance().select_single('ScopeItem') | ||
101 | 97 | scope_item.x.wait_for(0) | ||
102 | 98 | return scope_item.select_single(GenericScopeView) | ||
103 | 99 | |||
104 | 100 | |||
105 | 101 | class Preview(dash.Preview): | ||
106 | 102 | |||
107 | 103 | """Autopilot helper for the application preview.""" | ||
108 | 104 | |||
109 | 105 | def get_details(self): | ||
110 | 106 | """Return the details of the application whose preview is open.""" | ||
111 | 107 | header_widget = self.select_single('PreviewWidget', objectName='hdr') | ||
112 | 108 | title_label = header_widget.select_single( | ||
113 | 109 | 'Label', objectName='titleLabel') | ||
114 | 110 | subtitle_label = header_widget.select_single( | ||
115 | 111 | 'Label', objectName='subtitleLabel') | ||
116 | 112 | return dict( | ||
117 | 113 | title=title_label.text, subtitle=subtitle_label.text) | ||
118 | 114 | |||
119 | 115 | def install(self): | ||
120 | 116 | parent = self.get_parent() | ||
121 | 117 | install_button = self.select_single( | ||
122 | 118 | 'PreviewActionButton', objectName='buttoninstall_click') | ||
123 | 119 | self.pointing_device.click_object(install_button) | ||
124 | 120 | self.implicitHeight.wait_for(0) | ||
125 | 121 | parent.ready.wait_for(True) | ||
126 | 122 | |||
127 | 123 | def is_progress_bar_visible(self): | ||
128 | 124 | try: | ||
129 | 125 | self.select_single('ProgressBar', objectName='progressBar') | ||
130 | 126 | return True | ||
131 | 127 | except autopilot_dbus.StateNotFoundError: | ||
132 | 128 | return False | ||
133 | 0 | 129 | ||
134 | === modified file 'autopilot/unityclickscope/fake_servers.py' | |||
135 | --- autopilot/unityclickscope/fake_servers.py 2014-05-16 13:09:36 +0000 | |||
136 | +++ autopilot/unityclickscope/fake_servers.py 2014-07-07 21:14:23 +0000 | |||
137 | @@ -17,10 +17,16 @@ | |||
138 | 17 | import copy | 17 | import copy |
139 | 18 | import http.server | 18 | import http.server |
140 | 19 | import json | 19 | import json |
141 | 20 | import logging | ||
142 | 20 | import os | 21 | import os |
143 | 21 | import tempfile | 22 | import tempfile |
144 | 22 | import urllib.parse | 23 | import urllib.parse |
145 | 23 | 24 | ||
146 | 25 | import autopilot.logging | ||
147 | 26 | |||
148 | 27 | |||
149 | 28 | logger = logging.getLogger(__name__) | ||
150 | 29 | |||
151 | 24 | 30 | ||
152 | 25 | class BaseFakeHTTPRequestHandler(http.server.BaseHTTPRequestHandler): | 31 | class BaseFakeHTTPRequestHandler(http.server.BaseHTTPRequestHandler): |
153 | 26 | 32 | ||
154 | @@ -55,71 +61,167 @@ | |||
155 | 55 | class FakeSearchRequestHandler(BaseFakeHTTPRequestHandler): | 61 | class FakeSearchRequestHandler(BaseFakeHTTPRequestHandler): |
156 | 56 | 62 | ||
157 | 57 | _SEARCH_PATH = '/api/v1/search' | 63 | _SEARCH_PATH = '/api/v1/search' |
165 | 58 | _FAKE_SEARCH_RESPONSE_DICT = [ | 64 | _FAKE_DELTA_RESULTS = { |
166 | 59 | { | 65 | "publisher": "Rodney Dawes", |
167 | 60 | 'resource_url': 'https://TODO/api/v1/package/com.ubuntu.shorts', | 66 | "_links": { |
168 | 61 | 'icon_url': '{U1_SEARCH_BASE_URL}extra/shorts.png', | 67 | "self": { |
169 | 62 | 'price': 0.0, | 68 | "href": ( |
170 | 63 | 'name': 'com.ubuntu.shorts', | 69 | "{U1_SEARCH_BASE_URL}api/v1/" |
171 | 64 | 'title': 'Shorts' | 70 | "package/com.ubuntu.developer.dobey.delta-web") |
172 | 71 | } | ||
173 | 72 | }, | ||
174 | 73 | "architecture": ["all"], | ||
175 | 74 | "title": "Delta", | ||
176 | 75 | "icon_url": "http://TODO/delta-web.png", | ||
177 | 76 | "price": 0.0, | ||
178 | 77 | "name": "com.ubuntu.developer.dobey.delta-web" | ||
179 | 78 | } | ||
180 | 79 | _FAKE_SEARCH_RESPONSE_DICT = { | ||
181 | 80 | "_embedded": { | ||
182 | 81 | "clickindex:package": [_FAKE_DELTA_RESULTS] | ||
183 | 82 | }, | ||
184 | 83 | } | ||
185 | 84 | _FAKE_DELTA_DETAILS_DICT = { | ||
186 | 85 | "website": "", | ||
187 | 86 | "description": ( | ||
188 | 87 | "A simple web app for Delta.\n" | ||
189 | 88 | "Check in, view flight schedules, and book flights, on the Delta " | ||
190 | 89 | "mobile web site."), | ||
191 | 90 | "price": 0.0, | ||
192 | 91 | "date_published": "2014-05-03T15:30:16.431511Z", | ||
193 | 92 | "framework": ["ubuntu-sdk-14.04-qml-dev1"], | ||
194 | 93 | "terms_of_service": "", | ||
195 | 94 | "prices": {"USD": 0.0}, | ||
196 | 95 | "screenshot_url": "http://TODO/delta-web-checkin.png", | ||
197 | 96 | "category": "Utility", | ||
198 | 97 | "publisher": "Rodney Dawes", | ||
199 | 98 | "name": "com.ubuntu.developer.dobey.delta-web", | ||
200 | 99 | "license": "GNU GPL v3", | ||
201 | 100 | "title": "Delta", | ||
202 | 101 | "support_url": "https://launchpad.net/~dobey", | ||
203 | 102 | "icon_url": "http://TODO/delta-web.png", | ||
204 | 103 | "changelog": "", | ||
205 | 104 | "binary_filesize": 23728, | ||
206 | 105 | "download_url": ( | ||
207 | 106 | '{DOWNLOAD_BASE_URL}download/delta-dummy.click'), | ||
208 | 107 | "click_version": "0.1", | ||
209 | 108 | "developer_name": "Rodney Dawes", | ||
210 | 109 | "version": "1.0.1", | ||
211 | 110 | "company_name": "", | ||
212 | 111 | "keywords": [ | ||
213 | 112 | "delta", | ||
214 | 113 | "airlines", | ||
215 | 114 | "flight", | ||
216 | 115 | "status", | ||
217 | 116 | "schedules" | ||
218 | 117 | ], | ||
219 | 118 | "department": ["Accessories"], | ||
220 | 119 | "screenshot_urls": [ | ||
221 | 120 | "http://TODO/delta-web-checkin.png", | ||
222 | 121 | "https://TODO/delta-web-main.png" | ||
223 | 122 | ], | ||
224 | 123 | "architecture": ["all"] | ||
225 | 124 | } | ||
226 | 125 | _FAKE_DETAILS = { | ||
227 | 126 | 'com.ubuntu.developer.dobey.delta-web': _FAKE_DELTA_DETAILS_DICT | ||
228 | 127 | } | ||
229 | 128 | _FAKE_INDEX = { | ||
230 | 129 | "_embedded": { | ||
231 | 130 | "clickindex:department": [ | ||
232 | 131 | { | ||
233 | 132 | "has_children": False, | ||
234 | 133 | "_links": { | ||
235 | 134 | "self": { | ||
236 | 135 | "href": ( | ||
237 | 136 | "{U1_SEARCH_BASE_URL}api/v1/departments/" | ||
238 | 137 | "accessories") | ||
239 | 138 | } | ||
240 | 139 | }, | ||
241 | 140 | "name": "Accessories", | ||
242 | 141 | "slug": "accesories" | ||
243 | 142 | }, | ||
244 | 143 | ], | ||
245 | 144 | "clickindex:highlight": [ | ||
246 | 145 | { | ||
247 | 146 | "_embedded": { | ||
248 | 147 | "clickindex:package": [_FAKE_DELTA_RESULTS], | ||
249 | 148 | }, | ||
250 | 149 | "_links": { | ||
251 | 150 | "self": { | ||
252 | 151 | "href": ( | ||
253 | 152 | "{U1_SEARCH_BASE_URL}api/v1/highlights/" | ||
254 | 153 | "travel-apps") | ||
255 | 154 | } | ||
256 | 155 | }, | ||
257 | 156 | "name": "Travel apps", | ||
258 | 157 | "slug": "travel-apps" | ||
259 | 158 | }, | ||
260 | 159 | ], | ||
261 | 160 | }, | ||
262 | 161 | '_links': { | ||
263 | 162 | 'clickindex:department': { | ||
264 | 163 | 'href': "{U1_SEARCH_BASE_URL}api/v1/departments/{slug}", | ||
265 | 164 | 'templated': True, | ||
266 | 165 | 'title': 'Department' | ||
267 | 166 | }, | ||
268 | 167 | 'clickindex:departments': { | ||
269 | 168 | 'href': "{U1_SEARCH_BASE_URL}api/v1/departments", | ||
270 | 169 | 'title': 'Departments' | ||
271 | 170 | }, | ||
272 | 171 | 'clickindex:highlight': { | ||
273 | 172 | 'href': '{U1_SEARCH_BASE_URL}api/v1/highlights/{slug}', | ||
274 | 173 | 'templated': True, | ||
275 | 174 | 'title': 'Highlight' | ||
276 | 175 | }, | ||
277 | 176 | 'clickindex:highlights': { | ||
278 | 177 | 'href': '{U1_SEARCH_BASE_URL}api/v1/highlights', | ||
279 | 178 | 'title': 'Highlights' | ||
280 | 179 | }, | ||
281 | 180 | 'clickindex:package': { | ||
282 | 181 | 'href': '{U1_SEARCH_BASE_URL}api/v1/package/{name}', | ||
283 | 182 | 'templated': True, | ||
284 | 183 | 'title': 'Package' | ||
285 | 184 | }, | ||
286 | 185 | 'curies': [ | ||
287 | 186 | { | ||
288 | 187 | 'href': '{U1_SEARCH_BASE_URL}docs/v1/relations.html{#rel}', | ||
289 | 188 | 'name': 'clickindex', | ||
290 | 189 | 'templated': True | ||
291 | 190 | } | ||
292 | 191 | ], | ||
293 | 192 | 'search': { | ||
294 | 193 | 'href': '{U1_SEARCH_BASE_URL}api/v1/search{?q}', | ||
295 | 194 | 'templated': True, | ||
296 | 195 | 'title': 'Search' | ||
297 | 196 | }, | ||
298 | 197 | 'self': { | ||
299 | 198 | 'href': '{U1_SEARCH_BASE_URL}api/v1' | ||
300 | 199 | } | ||
301 | 65 | } | 200 | } |
302 | 66 | ] | ||
303 | 67 | _FAKE_SHORTS_DETAILS_DICT = { | ||
304 | 68 | 'website': 'https://launchpad.net/ubuntu-rssreader-app', | ||
305 | 69 | 'description': ( | ||
306 | 70 | 'Shorts is an rssreader application\n' | ||
307 | 71 | 'Shorts is an rss reader application that allows you to easily ' | ||
308 | 72 | 'search for new feeds.'), | ||
309 | 73 | 'price': 0.0, | ||
310 | 74 | 'framework': ["ubuntu-sdk-13.10"], | ||
311 | 75 | 'terms_of_service': '', | ||
312 | 76 | 'prices': {'USD': 0.0}, | ||
313 | 77 | 'screenshot_url': 'https://TODO/shorts0.png', | ||
314 | 78 | 'date_published': '2013-10-16T15:58:52.469000', | ||
315 | 79 | 'publisher': 'Ubuntu Click Loader', | ||
316 | 80 | 'name': 'com.ubuntu.shorts', | ||
317 | 81 | 'license': 'GNU GPL v3', | ||
318 | 82 | 'changelog': 'Test fixes', | ||
319 | 83 | 'support_url': 'mailto:ubuntu-touch-coreapps@lists.launchpad.net', | ||
320 | 84 | 'icon_url': 'https://TODO/shorts.png', | ||
321 | 85 | 'title': 'Shorts', | ||
322 | 86 | 'binary_filesize': 164944, | ||
323 | 87 | 'download_url': ( | ||
324 | 88 | '{DOWNLOAD_BASE_URL}download/shorts-dummy.click'), | ||
325 | 89 | 'click_version': '0.1', | ||
326 | 90 | 'developer_name': 'Ubuntu Click Loader', | ||
327 | 91 | 'version': '0.2.152', | ||
328 | 92 | 'company_name': '', | ||
329 | 93 | 'keywords': ['shorts', 'rss', 'news'], | ||
330 | 94 | 'screenshot_urls': [ | ||
331 | 95 | 'https://TODO/shorts0.png', | ||
332 | 96 | 'https://TODO/shorts1.png' | ||
333 | 97 | ], | ||
334 | 98 | 'architecture': ['all'] | ||
335 | 99 | } | ||
336 | 100 | _FAKE_DETAILS = { | ||
337 | 101 | 'com.ubuntu.shorts': _FAKE_SHORTS_DETAILS_DICT | ||
338 | 102 | } | 201 | } |
339 | 103 | 202 | ||
340 | 104 | def do_GET(self): | 203 | def do_GET(self): |
341 | 105 | parsed_path = urllib.parse.urlparse(self.path) | 204 | parsed_path = urllib.parse.urlparse(self.path) |
342 | 106 | if parsed_path.path.startswith(self._SEARCH_PATH): | 205 | if parsed_path.path.startswith(self._SEARCH_PATH): |
344 | 107 | self.send_json_reply(200, self._get_fake_search_response()) | 206 | self.send_search_results() |
345 | 108 | elif parsed_path.path.startswith('/extra/'): | 207 | elif parsed_path.path.startswith('/extra/'): |
346 | 109 | self.send_file(parsed_path.path[1:]) | 208 | self.send_file(parsed_path.path[1:]) |
347 | 110 | elif parsed_path.path.startswith('/api/v1/package/'): | 209 | elif parsed_path.path.startswith('/api/v1/package/'): |
348 | 111 | package = parsed_path.path[16:] | 210 | package = parsed_path.path[16:] |
349 | 112 | self.send_package_details(package) | 211 | self.send_package_details(package) |
350 | 212 | elif parsed_path.path.startswith('/api/v1'): | ||
351 | 213 | self.send_index() | ||
352 | 113 | else: | 214 | else: |
353 | 215 | logger.error( | ||
354 | 216 | 'Not implemented path in fake server: {}'.format(self.path)) | ||
355 | 114 | raise NotImplementedError(self.path) | 217 | raise NotImplementedError(self.path) |
356 | 115 | 218 | ||
363 | 116 | def _get_fake_search_response(self): | 219 | @autopilot.logging.log_action(logger.debug) |
364 | 117 | fake_search_response = copy.deepcopy(self._FAKE_SEARCH_RESPONSE_DICT) | 220 | def send_search_results(self): |
365 | 118 | for result in fake_search_response: | 221 | results = json.dumps(self._FAKE_SEARCH_RESPONSE_DICT) |
366 | 119 | result['icon_url'] = result['icon_url'].format( | 222 | self.send_json_reply(200, results) |
361 | 120 | U1_SEARCH_BASE_URL=os.environ.get('U1_SEARCH_BASE_URL')) | ||
362 | 121 | return json.dumps(fake_search_response) | ||
367 | 122 | 223 | ||
368 | 224 | @autopilot.logging.log_action(logger.debug) | ||
369 | 123 | def send_package_details(self, package): | 225 | def send_package_details(self, package): |
370 | 124 | details = copy.deepcopy(self._FAKE_DETAILS.get(package, None)) | 226 | details = copy.deepcopy(self._FAKE_DETAILS.get(package, None)) |
371 | 125 | if details is not None: | 227 | if details is not None: |
372 | @@ -130,6 +232,10 @@ | |||
373 | 130 | else: | 232 | else: |
374 | 131 | raise NotImplementedError(package) | 233 | raise NotImplementedError(package) |
375 | 132 | 234 | ||
376 | 235 | @autopilot.logging.log_action(logger.debug) | ||
377 | 236 | def send_index(self): | ||
378 | 237 | self.send_json_reply(200, json.dumps(self._FAKE_INDEX)) | ||
379 | 238 | |||
380 | 133 | 239 | ||
381 | 134 | class FakeDownloadServer(http.server.HTTPServer, object): | 240 | class FakeDownloadServer(http.server.HTTPServer, object): |
382 | 135 | 241 | ||
383 | 136 | 242 | ||
384 | === modified file 'autopilot/unityclickscope/test_click_scope.py' | |||
385 | --- autopilot/unityclickscope/test_click_scope.py 2014-05-26 08:06:08 +0000 | |||
386 | +++ autopilot/unityclickscope/test_click_scope.py 2014-07-07 21:14:23 +0000 | |||
387 | @@ -21,14 +21,12 @@ | |||
388 | 21 | 21 | ||
389 | 22 | import dbusmock | 22 | import dbusmock |
390 | 23 | import fixtures | 23 | import fixtures |
391 | 24 | from autopilot.introspection import dbus as autopilot_dbus | ||
392 | 25 | from autopilot.matchers import Eventually | 24 | from autopilot.matchers import Eventually |
393 | 26 | from testtools.matchers import Equals | 25 | from testtools.matchers import Equals |
394 | 27 | from unity8 import process_helpers | 26 | from unity8 import process_helpers |
395 | 28 | from unity8.shell import tests as unity_tests | 27 | from unity8.shell import tests as unity_tests |
399 | 29 | from unity8.shell.emulators import dash | 28 | |
400 | 30 | 29 | import unityclickscope | |
398 | 31 | |||
401 | 32 | from unityclickscope import credentials, fake_services, fixture_setup | 30 | from unityclickscope import credentials, fake_services, fixture_setup |
402 | 33 | 31 | ||
403 | 34 | 32 | ||
404 | @@ -53,11 +51,14 @@ | |||
405 | 53 | 51 | ||
406 | 54 | # We use fake servers by default because the current Jenkins | 52 | # We use fake servers by default because the current Jenkins |
407 | 55 | # configuration does not let us override the variables. | 53 | # configuration does not let us override the variables. |
408 | 56 | if os.environ.get('U1_SEARCH_BASE_URL', 'fake') == 'fake': | ||
409 | 57 | self._use_fake_server() | ||
410 | 58 | if os.environ.get('DOWNLOAD_BASE_URL', 'fake') == 'fake': | 54 | if os.environ.get('DOWNLOAD_BASE_URL', 'fake') == 'fake': |
411 | 59 | self._use_fake_download_server() | 55 | self._use_fake_download_server() |
412 | 60 | self._use_fake_download_service() | 56 | self._use_fake_download_service() |
413 | 57 | if os.environ.get('U1_SEARCH_BASE_URL', 'fake') == 'fake': | ||
414 | 58 | self._use_fake_server() | ||
415 | 59 | |||
416 | 60 | self.useFixture(fixtures.EnvironmentVariable('U1_DEBUG', newvalue='1')) | ||
417 | 61 | self._restart_scopes() | ||
418 | 61 | 62 | ||
419 | 62 | unity_proxy = self.launch_unity() | 63 | unity_proxy = self.launch_unity() |
420 | 63 | process_helpers.unlock_unity(unity_proxy) | 64 | process_helpers.unlock_unity(unity_proxy) |
421 | @@ -69,7 +70,6 @@ | |||
422 | 69 | self.useFixture(fake_search_server) | 70 | self.useFixture(fake_search_server) |
423 | 70 | self.useFixture(fixtures.EnvironmentVariable( | 71 | self.useFixture(fixtures.EnvironmentVariable( |
424 | 71 | 'U1_SEARCH_BASE_URL', newvalue=fake_search_server.url)) | 72 | 'U1_SEARCH_BASE_URL', newvalue=fake_search_server.url)) |
425 | 72 | self._restart_scope() | ||
426 | 73 | 73 | ||
427 | 74 | def _use_fake_download_server(self): | 74 | def _use_fake_download_server(self): |
428 | 75 | fake_download_server = fixture_setup.FakeDownloadServerRunning() | 75 | fake_download_server = fixture_setup.FakeDownloadServerRunning() |
429 | @@ -106,43 +106,78 @@ | |||
430 | 106 | dbus_mock.terminate() | 106 | dbus_mock.terminate() |
431 | 107 | dbus_mock.wait() | 107 | dbus_mock.wait() |
432 | 108 | 108 | ||
434 | 109 | def _restart_scope(self): | 109 | def _restart_scopes(self): |
435 | 110 | logging.info('Restarting click scope.') | 110 | logging.info('Restarting click scope.') |
436 | 111 | scope_runner_path = self._get_scoperunner_path() | ||
437 | 112 | apps_scope_ini_path, store_scope_ini_path = self._get_scopes_ini_path() | ||
438 | 113 | |||
439 | 111 | os.system('pkill -f -9 clickscope.ini') | 114 | os.system('pkill -f -9 clickscope.ini') |
445 | 112 | os.system( | 115 | os.system('pkill -f -9 clickstore.ini') |
446 | 113 | "dpkg-architecture -c " | 116 | |
447 | 114 | "'{scoperunner} \"\" {clickscope}' &".format( | 117 | os.system('{scoperunner} "" {appsscope} &'.format( |
448 | 115 | scoperunner=self._get_scoperunner_path(), | 118 | scoperunner=scope_runner_path, |
449 | 116 | clickscope=self._get_scope_ini_path())) | 119 | appsscope=apps_scope_ini_path)) |
450 | 120 | |||
451 | 121 | os.system('{scoperunner} "" {storescope} &'.format( | ||
452 | 122 | scoperunner=scope_runner_path, | ||
453 | 123 | storescope=store_scope_ini_path)) | ||
454 | 117 | 124 | ||
455 | 118 | def _get_scoperunner_path(self): | 125 | def _get_scoperunner_path(self): |
456 | 119 | return os.path.join( | 126 | return os.path.join( |
457 | 120 | self._get_installed_unity_scopes_lib_dir(), 'scoperunner') | 127 | self._get_installed_unity_scopes_lib_dir(), 'scoperunner') |
458 | 121 | 128 | ||
459 | 122 | def _get_installed_unity_scopes_lib_dir(self): | 129 | def _get_installed_unity_scopes_lib_dir(self): |
461 | 123 | return os.path.join('/usr/lib/$DEB_HOST_MULTIARCH/', 'unity-scopes') | 130 | arch = subprocess.check_output( |
462 | 131 | ["dpkg-architecture", "-qDEB_HOST_MULTIARCH"], | ||
463 | 132 | universal_newlines=True).strip() | ||
464 | 133 | return os.path.join('/usr/lib/{}/'.format(arch), 'unity-scopes') | ||
465 | 124 | 134 | ||
467 | 125 | def _get_scope_ini_path(self): | 135 | def _get_scopes_ini_path(self): |
468 | 126 | build_dir = os.environ.get('BUILD_DIR', None) | 136 | build_dir = os.environ.get('BUILD_DIR', None) |
469 | 127 | if build_dir is not None: | 137 | if build_dir is not None: |
471 | 128 | return self._get_built_scope_ini_path(build_dir) | 138 | return self._get_built_scopes_ini_path(build_dir) |
472 | 129 | else: | 139 | else: |
476 | 130 | return os.path.join( | 140 | app_scope_ini_path = os.path.join( |
477 | 131 | self._get_installed_unity_scopes_lib_dir(), | 141 | self._get_installed_unity_scopes_lib_dir(), |
478 | 132 | 'clickscope', 'clickscope.ini') | 142 | 'clickapps', 'clickscope.ini') |
479 | 143 | store_scope_ini_path = os.path.join( | ||
480 | 144 | self._get_installed_unity_scopes_lib_dir(), | ||
481 | 145 | 'clickstore', 'com.canonical.scopes.clickstore.ini') | ||
482 | 146 | return app_scope_ini_path, store_scope_ini_path | ||
483 | 133 | 147 | ||
485 | 134 | def _get_built_scope_ini_path(self, build_dir): | 148 | def _get_built_scopes_ini_path(self, build_dir): |
486 | 135 | # The ini and the so files need to be on the same directory. | 149 | # The ini and the so files need to be on the same directory. |
487 | 136 | # We copy them to a temp directory. | 150 | # We copy them to a temp directory. |
488 | 137 | temp_dir_fixture = fixtures.TempDir() | 151 | temp_dir_fixture = fixtures.TempDir() |
489 | 138 | self.useFixture(temp_dir_fixture) | 152 | self.useFixture(temp_dir_fixture) |
497 | 139 | shutil.copy( | 153 | |
498 | 140 | os.path.join(build_dir, 'data', 'clickscope.ini'), | 154 | built_apps_scope_ini = os.path.join( |
499 | 141 | temp_dir_fixture.path) | 155 | build_dir, 'data', 'clickscope.ini') |
500 | 142 | shutil.copy( | 156 | temp_apps_scope_dir = os.path.join(temp_dir_fixture.path, 'clickapps') |
501 | 143 | os.path.join(build_dir, 'scope', 'click', 'libclickscope.so'), | 157 | os.mkdir(temp_apps_scope_dir) |
502 | 144 | temp_dir_fixture.path) | 158 | shutil.copy(built_apps_scope_ini, temp_apps_scope_dir) |
503 | 145 | return os.path.join(temp_dir_fixture.path, 'clickscope.ini') | 159 | |
504 | 160 | built_apps_scope = os.path.join( | ||
505 | 161 | build_dir, 'scope', 'clickapps', 'scope.so') | ||
506 | 162 | shutil.copy(built_apps_scope, temp_apps_scope_dir) | ||
507 | 163 | |||
508 | 164 | built_store_scope_ini = os.path.join( | ||
509 | 165 | build_dir, 'data', 'com.canonical.scopes.clickstore.ini') | ||
510 | 166 | temp_store_scope_dir = os.path.join( | ||
511 | 167 | temp_dir_fixture.path, 'clickstore') | ||
512 | 168 | os.mkdir(temp_store_scope_dir) | ||
513 | 169 | shutil.copy(built_store_scope_ini, temp_store_scope_dir) | ||
514 | 170 | |||
515 | 171 | built_store_scope = os.path.join( | ||
516 | 172 | build_dir, 'scope', 'clickstore', | ||
517 | 173 | 'com.canonical.scopes.clickstore.so') | ||
518 | 174 | shutil.copy(built_store_scope, temp_store_scope_dir) | ||
519 | 175 | |||
520 | 176 | app_scope_ini_path = os.path.join( | ||
521 | 177 | temp_apps_scope_dir, 'clickscope.ini') | ||
522 | 178 | store_scope_ini_path = os.path.join( | ||
523 | 179 | temp_store_scope_dir, 'com.canonical.scopes.clickstore.ini') | ||
524 | 180 | return app_scope_ini_path, store_scope_ini_path | ||
525 | 146 | 181 | ||
526 | 147 | def _unlock_screen(self): | 182 | def _unlock_screen(self): |
527 | 148 | self.main_window.get_greeter().swipe() | 183 | self.main_window.get_greeter().swipe() |
528 | @@ -155,8 +190,8 @@ | |||
529 | 155 | def search(self, query): | 190 | def search(self, query): |
530 | 156 | search_indicator = self._proxy.select_single( | 191 | search_indicator = self._proxy.select_single( |
531 | 157 | 'SearchIndicator', objectName='search') | 192 | 'SearchIndicator', objectName='search') |
534 | 158 | self.touch.tap_object(search_indicator) | 193 | search_indicator.pointing_device.click_object(search_indicator) |
535 | 159 | self.dash.enter_search_query(query) | 194 | self.scope.enter_search_query(query) |
536 | 160 | 195 | ||
537 | 161 | def open_app_preview(self, category, name): | 196 | def open_app_preview(self, category, name): |
538 | 162 | self.search(name) | 197 | self.search(name) |
539 | @@ -172,40 +207,46 @@ | |||
540 | 172 | self.assertThat(scope.isCurrent, Equals(True)) | 207 | self.assertThat(scope.isCurrent, Equals(True)) |
541 | 173 | 208 | ||
542 | 174 | 209 | ||
544 | 175 | class TestCaseWithClickScopeOpen(BaseClickScopeTestCase): | 210 | class BaseTestCaseWithStoreScopeOpen(BaseClickScopeTestCase): |
545 | 176 | 211 | ||
546 | 177 | def setUp(self): | 212 | def setUp(self): |
549 | 178 | super(TestCaseWithClickScopeOpen, self).setUp() | 213 | super(BaseTestCaseWithStoreScopeOpen, self).setUp() |
550 | 179 | self.scope = self.open_scope() | 214 | app_scope = self.open_scope() |
551 | 215 | self.scope = app_scope.go_to_store() | ||
552 | 216 | |||
553 | 217 | |||
554 | 218 | class TestCaseWithStoreScopeOpen(BaseTestCaseWithStoreScopeOpen): | ||
555 | 180 | 219 | ||
556 | 181 | def test_search_available_app(self): | 220 | def test_search_available_app(self): |
558 | 182 | self.search('Shorts') | 221 | self.search('Delta') |
559 | 183 | applications = self.scope.get_applications('appstore') | 222 | applications = self.scope.get_applications('appstore') |
561 | 184 | self.assertThat(applications[0], Equals('Shorts')) | 223 | self.assertThat(applications[0], Equals('Delta')) |
562 | 185 | 224 | ||
563 | 186 | def test_open_app_preview(self): | 225 | def test_open_app_preview(self): |
564 | 187 | expected_details = dict( | 226 | expected_details = dict( |
567 | 188 | title='Shorts', subtitle='Ubuntu Click Loader') | 227 | title='Delta', subtitle='Rodney Dawes') |
568 | 189 | preview = self.open_app_preview('appstore', 'Shorts') | 228 | preview = self.open_app_preview('appstore', 'Delta') |
569 | 190 | details = preview.get_details() | 229 | details = preview.get_details() |
570 | 191 | self.assertEqual(details, expected_details) | 230 | self.assertEqual(details, expected_details) |
571 | 192 | 231 | ||
572 | 193 | def test_install_without_credentials(self): | 232 | def test_install_without_credentials(self): |
574 | 194 | preview = self.open_app_preview('appstore', 'Shorts') | 233 | preview = self.open_app_preview('appstore', 'Delta') |
575 | 195 | preview.install() | 234 | preview.install() |
577 | 196 | error = self.dash.wait_select_single(Preview) | 235 | error = self.dash.wait_select_single(unityclickscope.Preview) |
578 | 197 | 236 | ||
579 | 198 | details = error.get_details() | 237 | details = error.get_details() |
580 | 199 | self.assertEqual('Login Error', details.get('title')) | 238 | self.assertEqual('Login Error', details.get('title')) |
581 | 200 | 239 | ||
582 | 201 | 240 | ||
584 | 202 | class ClickScopeTestCaseWithCredentials(BaseClickScopeTestCase): | 241 | class ClickScopeTestCaseWithCredentials(BaseTestCaseWithStoreScopeOpen): |
585 | 203 | 242 | ||
586 | 204 | def setUp(self): | 243 | def setUp(self): |
587 | 244 | self.skipTest( | ||
588 | 245 | 'We cannot add credentials yet because the keyring dialog will be ' | ||
589 | 246 | 'opened prompting for a password. http://pad.lv/1338714') | ||
590 | 205 | self.add_u1_credentials() | 247 | self.add_u1_credentials() |
591 | 206 | super(ClickScopeTestCaseWithCredentials, self).setUp() | 248 | super(ClickScopeTestCaseWithCredentials, self).setUp() |
594 | 207 | self.scope = self.open_scope() | 249 | self.preview = self.open_app_preview('appstore', 'Delta') |
593 | 208 | self.preview = self.open_app_preview('appstore', 'Shorts') | ||
595 | 209 | 250 | ||
596 | 210 | def add_u1_credentials(self): | 251 | def add_u1_credentials(self): |
597 | 211 | account_manager = credentials.AccountManager() | 252 | account_manager = credentials.AccountManager() |
598 | @@ -224,36 +265,3 @@ | |||
599 | 224 | self.preview.install() | 265 | self.preview.install() |
600 | 225 | self.assertThat( | 266 | self.assertThat( |
601 | 226 | self.preview.is_progress_bar_visible, Eventually(Equals(True))) | 267 | self.preview.is_progress_bar_visible, Eventually(Equals(True))) |
602 | 227 | |||
603 | 228 | |||
604 | 229 | class DashApps(dash.DashApps): | ||
605 | 230 | """Autopilot emulator for the applicatios scope.""" | ||
606 | 231 | |||
607 | 232 | |||
608 | 233 | class Preview(dash.Preview): | ||
609 | 234 | """Autopilot emulator for the application preview.""" | ||
610 | 235 | |||
611 | 236 | def get_details(self): | ||
612 | 237 | """Return the details of the application whose preview is open.""" | ||
613 | 238 | header_widget = self.select_single('PreviewWidget', objectName='hdr') | ||
614 | 239 | title_label = header_widget.select_single( | ||
615 | 240 | 'Label', objectName='titleLabel') | ||
616 | 241 | subtitle_label = header_widget.select_single( | ||
617 | 242 | 'Label', objectName='subtitleLabel') | ||
618 | 243 | return dict( | ||
619 | 244 | title=title_label.text, subtitle=subtitle_label.text) | ||
620 | 245 | |||
621 | 246 | def install(self): | ||
622 | 247 | parent = self.get_parent() | ||
623 | 248 | install_button = self.select_single( | ||
624 | 249 | 'PreviewActionButton', objectName='buttoninstall_click') | ||
625 | 250 | self.pointing_device.click_object(install_button) | ||
626 | 251 | self.implicitHeight.wait_for(0) | ||
627 | 252 | parent.ready.wait_for(True) | ||
628 | 253 | |||
629 | 254 | def is_progress_bar_visible(self): | ||
630 | 255 | try: | ||
631 | 256 | self.select_single('ProgressBar', objectName='progressBar') | ||
632 | 257 | return True | ||
633 | 258 | except autopilot_dbus.StateNotFoundError: | ||
634 | 259 | return False |
PASSED: Continuous integration, rev:299 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- ci/156/ jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- amd64-ci/ 131 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 130 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 130/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- i386-ci/ 130
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- team-unity- scope-click- devel-ci/ 156/rebuild
http://