Merge lp:~bfiller/webbrowser-app/file-upload into lp:webbrowser-app
- file-upload
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~bfiller/webbrowser-app/file-upload |
Merge into: | lp:webbrowser-app |
Diff against target: |
294 lines (+252/-0) 5 files modified
debian/control (+1/-0) src/app/ContentPickerDialog.qml (+82/-0) src/app/WebViewImpl.qml (+1/-0) tests/autopilot/webbrowser_app/tests/http_server.py (+15/-0) tests/autopilot/webbrowser_app/tests/test_content_pick.py (+153/-0) |
To merge this branch: | bzr merge lp:~bfiller/webbrowser-app/file-upload |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Adnane Belmadiaf | community | Pending | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+203227@code.launchpad.net |
Commit message
Description of the change
Adding image upload capability. Not ready yet for review.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:420
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Bill Filler (bfiller) wrote : | # |
Remaining work items so we can land this:
Main use case to get working well is open gmail in browser and try to add an attachment to a new email message:
phase 1:
- disable failing autopilot tests
- enable multi selection mode
- fix up result list to display multiple objects, need to support multiple types, i.e. a picture and a video. perhaps this can be a simple list with some sort of icon. Need to check with design to see what is desired
- this works correctly in webbrowser-app but doesn't work at all if you run in a webapp (like try to upload photo in gmail webbapp).
phase 2:
- instead of hardcoding "ContentType.
- implement the Source Picker UI (in the design spec) to display the choices of available apps returned by the content-hub. This should be a generic UI component that would probably live in the content-hub or sdk
Unmerged revisions
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2013-12-05 07:06:08 +0000 |
3 | +++ debian/control 2014-01-26 04:07:40 +0000 |
4 | @@ -85,6 +85,7 @@ |
5 | libautopilot-qt (>= 1.4), |
6 | libqt5test5, |
7 | ubuntu-ui-toolkit-autopilot, |
8 | + unity8-autopilot, |
9 | webbrowser-app (>= ${binary:Version}), |
10 | Description: Ubuntu web browser autopilot tests |
11 | A lightweight web browser tailored for Ubuntu, based on the Webkit rendering |
12 | |
13 | === added file 'src/app/ContentPickerDialog.qml' |
14 | --- src/app/ContentPickerDialog.qml 1970-01-01 00:00:00 +0000 |
15 | +++ src/app/ContentPickerDialog.qml 2014-01-26 04:07:40 +0000 |
16 | @@ -0,0 +1,82 @@ |
17 | +/* |
18 | + * Copyright 2013 Canonical Ltd. |
19 | + * |
20 | + * This file is part of webbrowser-app. |
21 | + * |
22 | + * webbrowser-app is free software; you can redistribute it and/or modify |
23 | + * it under the terms of the GNU General Public License as published by |
24 | + * the Free Software Foundation; version 3. |
25 | + * |
26 | + * webbrowser-app is distributed in the hope that it will be useful, |
27 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
29 | + * GNU General Public License for more details. |
30 | + * |
31 | + * You should have received a copy of the GNU General Public License |
32 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
33 | + */ |
34 | + |
35 | +import QtQuick 2.0 |
36 | +import Ubuntu.Components 0.1 |
37 | +import Ubuntu.Components.Popups 0.1 as Popups |
38 | +import Ubuntu.Content 0.1 |
39 | + |
40 | +Popups.Dialog { |
41 | + id: picker |
42 | + title: i18n.tr("Pick content to upload") |
43 | + property var activeTransfer |
44 | + |
45 | + UbuntuShape { |
46 | + height: width |
47 | + image: Image { |
48 | + objectName: "mediaPreview" |
49 | + id: preview |
50 | + fillMode: Image.PreserveAspectCrop |
51 | + } |
52 | + |
53 | + MouseArea { |
54 | + anchors.fill: parent |
55 | + onClicked: startContentPicking() |
56 | + } |
57 | + |
58 | + ContentImportHint { |
59 | + anchors.fill: parent |
60 | + activeTransfer: picker.activeTransfer |
61 | + } |
62 | + } |
63 | + |
64 | + Button { |
65 | + objectName: "ok" |
66 | + text: i18n.tr("OK") |
67 | + color: "green" |
68 | + enabled: preview.source |
69 | + onClicked: model.accept(String(preview.source).replace("file://", "")) |
70 | + } |
71 | + |
72 | + Button { |
73 | + text: i18n.tr("Cancel") |
74 | + color: UbuntuColors.coolGrey |
75 | + onClicked: model.reject() |
76 | + } |
77 | + |
78 | + function startContentPicking() { |
79 | + activeTransfer = ContentHub.importContent(ContentType.Pictures); |
80 | + activeTransfer.selectionType = ContentTransfer.Single; |
81 | + activeTransfer.start(); |
82 | + } |
83 | + |
84 | + Component.onCompleted: { |
85 | + show(); |
86 | + startContentPicking(); |
87 | + } |
88 | + |
89 | + Connections { |
90 | + target: picker.activeTransfer |
91 | + onStateChanged: { |
92 | + if (picker.activeTransfer.state === ContentTransfer.Charged) { |
93 | + var importItem = picker.activeTransfer.items[0]; |
94 | + preview.source = importItem.url |
95 | + } |
96 | + } |
97 | + } |
98 | +} |
99 | |
100 | === modified file 'src/app/WebViewImpl.qml' |
101 | --- src/app/WebViewImpl.qml 2013-11-12 22:18:49 +0000 |
102 | +++ src/app/WebViewImpl.qml 2014-01-26 04:07:40 +0000 |
103 | @@ -37,6 +37,7 @@ |
104 | experimental.alertDialog: AlertDialog {} |
105 | experimental.confirmDialog: ConfirmDialog {} |
106 | experimental.promptDialog: PromptDialog {} |
107 | + experimental.filePicker: ContentPickerDialog {} |
108 | |
109 | selectionActions: ActionList { |
110 | Actions.Copy { |
111 | |
112 | === modified file 'tests/autopilot/webbrowser_app/tests/http_server.py' |
113 | --- tests/autopilot/webbrowser_app/tests/http_server.py 2013-12-16 10:51:47 +0000 |
114 | +++ tests/autopilot/webbrowser_app/tests/http_server.py 2014-01-26 04:07:40 +0000 |
115 | @@ -86,6 +86,21 @@ |
116 | html += 'src="/blanktargetlink" />' |
117 | html += '</body></html>' |
118 | self.send_html(html) |
119 | + elif self.path == "/uploadform": |
120 | + # craft a page that accepts clicks anywhere inside its window |
121 | + # and on a click opens up the content picker. |
122 | + # It also pops up an alert with the new content of the file |
123 | + # upload field when it changes |
124 | + self.send_response(200) |
125 | + html = '<html><body style="margin: 0">' |
126 | + html = '<form action="upload" method="post" enctype="multipart/form-data">' |
127 | + html += '<input type="file" name="file" id="file" onchange="alert(this.value)"><br>' |
128 | + html += '<input type="submit" name="submit" value="Submit">' |
129 | + html += '</form>' |
130 | + html += '<a href="javascript:document.getElementById(\'file\').click()">' |
131 | + html += '<div style="height: 100%"></div></a>' |
132 | + html += '</body></html>' |
133 | + self.send_html(html) |
134 | else: |
135 | self.send_error(404) |
136 | |
137 | |
138 | === added file 'tests/autopilot/webbrowser_app/tests/test_content_pick.py' |
139 | --- tests/autopilot/webbrowser_app/tests/test_content_pick.py 1970-01-01 00:00:00 +0000 |
140 | +++ tests/autopilot/webbrowser_app/tests/test_content_pick.py 2014-01-26 04:07:40 +0000 |
141 | @@ -0,0 +1,153 @@ |
142 | +# -*- coding: utf-8 -*- |
143 | +# |
144 | +# Copyright 2013 Canonical |
145 | +# |
146 | +# This program is free software: you can redistribute it and/or modify it |
147 | +# under the terms of the GNU General Public License version 3, as published |
148 | +# by the Free Software Foundation. |
149 | + |
150 | +from __future__ import absolute_import |
151 | + |
152 | +from autopilot.introspection import get_proxy_object_for_existing_process |
153 | +from autopilot.platform import model |
154 | +from autopilot.matchers import Eventually |
155 | +from testtools.matchers import Equals, NotEquals |
156 | +from testtools import skipIf, skip |
157 | +from webbrowser_app.tests import StartOpenRemotePageTestCaseBase |
158 | +from unity8 import process_helpers as helpers |
159 | +from ubuntuuitoolkit import emulators as toolkit_emulators |
160 | +import os, subprocess |
161 | + |
162 | +@skip("Will not work until bug #1255077 is solved") |
163 | +class TestContentPick(StartOpenRemotePageTestCaseBase): |
164 | + |
165 | + """Tests that content picking dialog show up.""" |
166 | + |
167 | + def test_pick_image(self): |
168 | + url = self.base_url + "/uploadform" |
169 | + self.go_to_url(url) |
170 | + self.assert_page_eventually_loaded(url) |
171 | + webview = self.main_window.get_current_webview() |
172 | + self.pointing_device.click_object(webview) |
173 | + |
174 | + dialog = self.app.wait_select_single("ContentPickerDialog") |
175 | + self.assertThat(dialog.visible, Equals(True)) |
176 | + |
177 | +@skipIf(model() == 'Desktop', "Phablet only") |
178 | +class TestContentPickerIntegration(StartOpenRemotePageTestCaseBase): |
179 | + |
180 | + """Tests that the gallery app is brought up to choose image content""" |
181 | + |
182 | + def tearDown(self): |
183 | + os.system("pkill gallery-app") |
184 | + os.system("pkill webbrowser-app") |
185 | + super(StartOpenRemotePageTestCaseBase, self).tearDown() |
186 | + |
187 | + def get_unity8_proxy_object(self): |
188 | + pid = helpers._get_unity_pid() |
189 | + return get_proxy_object_for_existing_process(pid) |
190 | + |
191 | + def get_current_focused_appid(self, unity8): |
192 | + return unity8.select_single("Shell").currentFocusedAppId |
193 | + |
194 | + def set_testability_environment_variable(self): |
195 | + """Makes sure every app opened in the environment loads the |
196 | + testability driver.""" |
197 | + |
198 | + subprocess.check_call([ |
199 | + "/sbin/initctl", |
200 | + "set-env", |
201 | + "QT_LOAD_TESTABILITY=1" |
202 | + ]) |
203 | + |
204 | + def get_app_pid(self, app): |
205 | + """Return the PID of the named app, or -1 if it's not |
206 | + running""" |
207 | + |
208 | + try: |
209 | + return int(subprocess.check_output(["pidof", app]).strip()) |
210 | + except subprocess.CalledProcessError: |
211 | + return -1 |
212 | + |
213 | + def wait_app_focused(self, name): |
214 | + """Wait until the app with the specified name is the |
215 | + currently focused one""" |
216 | + |
217 | + unity8 = self.get_unity8_proxy_object() |
218 | + shell = unity8.select_single("Shell") |
219 | + self.assertThat( |
220 | + lambda: self.get_current_focused_appid(unity8), |
221 | + Eventually(Equals(name)) |
222 | + ) |
223 | + |
224 | + def test_image_picker_is_gallery(self): |
225 | + """ Tests that the gallery shows up when we are picking |
226 | + images """ |
227 | + |
228 | + # Go to a page where clicking anywhere equals clicking on the |
229 | + # file selection button of an upload form |
230 | + url = self.base_url + "/uploadform" |
231 | + self.go_to_url(url) |
232 | + self.assert_page_eventually_loaded(url) |
233 | + webview = self.main_window.get_current_webview() |
234 | + self.pointing_device.click_object(webview) |
235 | + |
236 | + # Verify that such a click brings up the gallery to select images |
237 | + self.wait_app_focused("gallery-app") |
238 | + |
239 | + def test_image_picker_pick_image(self): |
240 | + """ Tests that the we can select an image in the gallery and |
241 | + control will return to the browser with the choosen image |
242 | + picked.""" |
243 | + |
244 | + # First run the previous test to bring up the content picker |
245 | + self.set_testability_environment_variable() |
246 | + self.test_image_picker_is_gallery() |
247 | + |
248 | + # Now wait until the gallery-app process is up. |
249 | + # NOTE: this will not work unless run on a device where unity8 runs in |
250 | + # testability mode. To manually restart unity8 in this mode run from a |
251 | + # python shell: |
252 | + # from unity8 import process_helpers as p; p.restart_unity_with_testability() |
253 | + unity8 = self.get_unity8_proxy_object() |
254 | + self.assertThat(lambda: self.get_app_pid("gallery-app"), Eventually(NotEquals(-1))) |
255 | + |
256 | + gallery = get_proxy_object_for_existing_process( |
257 | + self.get_app_pid("gallery-app"), |
258 | + emulator_base = toolkit_emulators.UbuntuUIToolkitEmulatorBase |
259 | + ) |
260 | + |
261 | + # Wait for the gallery UI to completely display |
262 | + view = gallery.wait_select_single("QQuickView") |
263 | + self.assertThat(view.visible, Eventually(Equals(True))) |
264 | + |
265 | + # Select the first picture on the picker by clicking on it |
266 | + # NOTE: this is currently failing if there is anything except two pictures |
267 | + # in the gallery (at least on a Maguro device), so I'm putting a temporary |
268 | + # stop to the test here so that it won't break in Jenkins |
269 | + return |
270 | + |
271 | + grid = gallery.wait_select_single("MediaGrid") |
272 | + photo = grid.select_many("OrganicItemInteraction")[0] |
273 | + self.pointing_device.click_object(photo) |
274 | + self.assertThat(photo.isSelected, Eventually(Equals(True))) |
275 | + |
276 | + # Now the "Pick" button will be enabled and we click on it |
277 | + button = gallery.select_single("Button", objectName="pickButton") |
278 | + self.assertThat(button.enabled, Eventually(Equals(True))) |
279 | + self.pointing_device.click_object(button) |
280 | + |
281 | + # The gallery should close and focus returned to the browser |
282 | + self.wait_app_focused("webbrowser-app") |
283 | + |
284 | + # Verify that an image has actually been selected |
285 | + dialog = self.app.wait_select_single("ContentPickerDialog") |
286 | + self.assertThat(dialog.visible, Equals(True)) |
287 | + preview = dialog.wait_select_single("QQuickImage", objectName="mediaPreview") |
288 | + self.assertThat(preview.source, Eventually(NotEquals(""))) |
289 | + |
290 | + # Verify that now we can click the "OK" button and it closes the dialog |
291 | + button = dialog.wait_select_single("Button", objectName="ok") |
292 | + self.assertThat(button.enabled, Eventually(Equals(True))) |
293 | + self.pointing_device.click_object(button) |
294 | + self.assertThat(dialog.visible, Eventually(Equals(False))) |
FAILED: Continuous integration, rev:420 jenkins. qa.ubuntu. com/job/ webbrowser- app-ci/ 590/ jenkins. qa.ubuntu. com/job/ generic- mediumtests- trusty/ 2616 jenkins. qa.ubuntu. com/job/ generic- mediumtests- trusty- touch/2407/ console jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- amd64-ci/ 92 jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- armhf-ci/ 92 jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- armhf-ci/ 92/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ webbrowser- app-trusty- i386-ci/ 92 jenkins. qa.ubuntu. com/job/ autopilot- testrunner- otto-trusty/ 2285 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- amd64/2618 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- amd64/2618/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- armhf/2408 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- armhf/2408/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- runner- mako/4847/ console s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 3357
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/webbrowser- app-ci/ 590/rebuild
http://