Merge lp:~dobey/ubuntuone-credentials/update-13-10 into lp:ubuntuone-credentials/stable-13-10
- update-13-10
- Merge into stable-13-10
Proposed by
dobey
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | 33 |
Merged at revision: | 33 |
Proposed branch: | lp:~dobey/ubuntuone-credentials/update-13-10 |
Merge into: | lp:ubuntuone-credentials/stable-13-10 |
Diff against target: |
750 lines (+432/-7) 20 files modified
CMakeLists.txt (+1/-1) libubuntuoneauth/errormessages.h (+3/-1) libubuntuoneauth/network.cpp (+0/-2) libubuntuoneauth/responses.h (+1/-1) online-accounts-provider/ButtonRow.qml (+2/-0) online-accounts-provider/CMakeLists.txt (+2/-0) online-accounts-provider/ExistingAccount.qml (+4/-0) online-accounts-provider/LoginForm.qml (+4/-1) online-accounts-provider/Main.qml (+12/-0) online-accounts-provider/NewAccount.qml (+6/-0) online-accounts-provider/RegisterForm.qml (+7/-0) online-accounts-provider/tests/CMakeLists.txt (+10/-0) online-accounts-provider/tests/autopilot/TestWrapperExisting.qml (+42/-0) online-accounts-provider/tests/autopilot/TestWrapperNew.qml (+48/-0) online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/__init__.py (+124/-0) online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/__init__.py (+1/-0) online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/test_main.py (+144/-0) online-accounts-provider/tests/autopilot/run (+12/-0) qml-credentials-service/CMakeLists.txt (+3/-0) qml-credentials-service/ubuntuone_credentials_service.cpp (+6/-1) |
To merge this branch: | bzr merge lp:~dobey/ubuntuone-credentials/update-13-10 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mike McCracken (community) | Approve | ||
Review via email: mp+189411@code.launchpad.net |
Commit message
[Michael McCracken]
- Hide keyboard when user submits form, making error message visible. (LP: #1231580)
- Use email-specific keyboard layout and avoid storing passwords in predictive input dictionary. (LP: #1235282)
- Provide general user-friendly error message for network errors. (LP: #1233951)
- Delete incomplete account when user uses back button to cancel account creation. (LP: #1234285)
- Add GUI-level autopilot functional test suite to online-
Description of the change
To post a comment you must log in.
Revision history for this message
Mike McCracken (mikemc) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2013-09-16 17:44:17 +0000 |
3 | +++ CMakeLists.txt 2013-10-04 19:17:45 +0000 |
4 | @@ -10,7 +10,7 @@ |
5 | SET (AUTH_LIB_API_VERSION 2.0) |
6 | SET (AUTH_LIB_NAME ubuntuoneauth-${AUTH_LIB_API_VERSION}) |
7 | |
8 | -# these names are also used in qml-credentials-service/qmldir, be sure to change them in both places |
9 | +# these names are used in qml-credentials-service/qmldir.template |
10 | SET (QML_MODULE_NAME UbuntuOne) |
11 | SET (QML_PLUGIN_API_VERSION 1.0) |
12 | SET (QML_PLUGIN_NAME UbuntuOneCredentialsPlugin-${QML_PLUGIN_API_VERSION}) |
13 | |
14 | === modified file 'libubuntuoneauth/errormessages.h' |
15 | --- libubuntuoneauth/errormessages.h 2013-06-14 22:30:19 +0000 |
16 | +++ libubuntuoneauth/errormessages.h 2013-10-04 19:17:45 +0000 |
17 | @@ -1,6 +1,9 @@ |
18 | #ifndef ERROR_MESSAGES_H |
19 | #define ERROR_MESSAGES_H |
20 | |
21 | + |
22 | +#define NO_HTTP_REASON "No HTTP error reason" |
23 | + |
24 | #define LOGIN_FAILED "LOGIN_FAILED" |
25 | #define CAPTCHA_REQUIRED "CAPTCHA_REQUIRED" |
26 | #define INVALID_CREDENTIALS "INVALID_CREDENTIALS" |
27 | @@ -11,7 +14,6 @@ |
28 | #define CAN_NOT_RESET_PASSWORD "CAN_NOT_RESET_PASSWORD" |
29 | #define ALREADY_REGISTERED "ALREADY_REGISTERED" |
30 | |
31 | - |
32 | enum ErrorCodes |
33 | { |
34 | CODE_LOGIN_FAILED = 0, |
35 | |
36 | === modified file 'libubuntuoneauth/network.cpp' |
37 | --- libubuntuoneauth/network.cpp 2013-07-23 15:47:07 +0000 |
38 | +++ libubuntuoneauth/network.cpp 2013-10-04 19:17:45 +0000 |
39 | @@ -28,8 +28,6 @@ |
40 | #include "responses.h" |
41 | #include "requests.h" |
42 | |
43 | -#define NO_HTTP_REASON QString("No HTTP error reason") |
44 | - |
45 | namespace UbuntuOne { |
46 | |
47 | Network::Network(QObject *parent) |
48 | |
49 | === modified file 'libubuntuoneauth/responses.h' |
50 | --- libubuntuoneauth/responses.h 2013-06-14 22:39:59 +0000 |
51 | +++ libubuntuoneauth/responses.h 2013-10-04 19:17:45 +0000 |
52 | @@ -131,4 +131,4 @@ |
53 | |
54 | } /* end UbuntuOne namespace */ |
55 | |
56 | -#endif /* _REQUESTS_H_ */ |
57 | +#endif /* _RESPONSES_H_ */ |
58 | |
59 | === modified file 'online-accounts-provider/ButtonRow.qml' |
60 | --- online-accounts-provider/ButtonRow.qml 2013-09-13 18:49:09 +0000 |
61 | +++ online-accounts-provider/ButtonRow.qml 2013-10-04 19:17:45 +0000 |
62 | @@ -7,6 +7,7 @@ |
63 | spacing: units.gu(1) |
64 | Button { |
65 | id: btnCancel |
66 | + objectName: "cancelButton" |
67 | text: "Cancel" |
68 | color: "#1c091a" |
69 | height: parent.height |
70 | @@ -17,6 +18,7 @@ |
71 | } |
72 | Button { |
73 | id: btnContinue |
74 | + objectName: "continueButton" |
75 | text: "Continue" |
76 | color: "#cc3300" |
77 | height: parent.height |
78 | |
79 | === modified file 'online-accounts-provider/CMakeLists.txt' |
80 | --- online-accounts-provider/CMakeLists.txt 2013-08-26 19:51:56 +0000 |
81 | +++ online-accounts-provider/CMakeLists.txt 2013-10-04 19:17:45 +0000 |
82 | @@ -4,3 +4,5 @@ |
83 | set (QML_PLUGIN_INSTALL_DIR share/accounts/qml-plugins/ubuntuone/) |
84 | |
85 | install (FILES ${QML_PLUGIN_FILES} DESTINATION ${QML_PLUGIN_INSTALL_DIR}) |
86 | + |
87 | +add_subdirectory(tests) |
88 | \ No newline at end of file |
89 | |
90 | === modified file 'online-accounts-provider/ExistingAccount.qml' |
91 | --- online-accounts-provider/ExistingAccount.qml 2013-09-12 14:59:06 +0000 |
92 | +++ online-accounts-provider/ExistingAccount.qml 2013-10-04 19:17:45 +0000 |
93 | @@ -33,6 +33,7 @@ |
94 | anchors.right: parent.right |
95 | |
96 | ListItem.SingleValue { |
97 | + objectName: "emailListItem" |
98 | text: "Email" |
99 | value: account.displayName |
100 | } |
101 | @@ -45,6 +46,7 @@ |
102 | |
103 | ListItem.SingleControl { |
104 | control: Button { |
105 | + objectName: "removeAccountButton" |
106 | text: "Remove account…" |
107 | width: parent.width - units.gu(4) |
108 | onClicked: PopupUtils.open(removalConfirmationComponent); |
109 | @@ -64,6 +66,7 @@ |
110 | |
111 | Button { |
112 | text: "Remove" |
113 | + objectName: "confirmRemoveAccountButton" |
114 | onClicked: { |
115 | PopupUtils.close(dialog); |
116 | console.debug("Removing account ID: " + account.accountId); |
117 | @@ -76,6 +79,7 @@ |
118 | |
119 | Button { |
120 | text: "Cancel" |
121 | + objectName: "cancelRemoveAccountButton" |
122 | onClicked: { |
123 | console.log("User cancelled account removal"); |
124 | PopupUtils.close(dialog); |
125 | |
126 | === modified file 'online-accounts-provider/LoginForm.qml' |
127 | --- online-accounts-provider/LoginForm.qml 2013-09-13 18:31:34 +0000 |
128 | +++ online-accounts-provider/LoginForm.qml 2013-10-04 19:17:45 +0000 |
129 | @@ -19,7 +19,7 @@ |
130 | |
131 | TextField { |
132 | id: passwordTextField |
133 | - |
134 | + objectName: "loginFormPasswordTextField" |
135 | placeholderText: "Your password" |
136 | echoMode: TextInput.Password |
137 | width: main.width - (2 * main.anchors.margins) |
138 | @@ -27,6 +27,7 @@ |
139 | Keys.onReturnPressed: main.processForm(); |
140 | KeyNavigation.tab: twoFactorUI.visible ? twoFactorTextField : emailTextField /* from main */ |
141 | KeyNavigation.backtab: emailTextField /* from main */ |
142 | + inputMethodHints: Qt.ImhSensitiveData |
143 | } |
144 | |
145 | Label { |
146 | @@ -36,6 +37,7 @@ |
147 | } |
148 | |
149 | ButtonRow { |
150 | + objectName: "buttonRow-LoginForm-noTwoFactor" |
151 | anchors.left: parent.left |
152 | anchors.right: parent.right |
153 | |
154 | @@ -54,6 +56,7 @@ |
155 | |
156 | TextField { |
157 | id: twoFactorTextField |
158 | + objectName: "twoFactorTextField" |
159 | placeholderText: "2-factor device code" |
160 | echoMode: TextInput.Password |
161 | width: main.width - (2 * main.anchors.margins) |
162 | |
163 | === modified file 'online-accounts-provider/Main.qml' |
164 | --- online-accounts-provider/Main.qml 2013-09-13 18:31:34 +0000 |
165 | +++ online-accounts-provider/Main.qml 2013-10-04 19:17:45 +0000 |
166 | @@ -53,6 +53,17 @@ |
167 | } |
168 | |
169 | Connections { |
170 | + target: rootFlickable.parent.parent.tools.back; |
171 | + onTriggered: { |
172 | + console.debug("page back button clicked, deleting incomplete account."); |
173 | + if(account.accountId != 0) { |
174 | + account.remove(Account.RemoveCredentials); |
175 | + editPageLoader.item.resetUI(); |
176 | + } |
177 | + } |
178 | + } |
179 | + |
180 | + Connections { |
181 | target: account |
182 | onSynced: { |
183 | console.debug("Account id " + account.accountId + " synced. account.displayName: " + account.displayName) |
184 | @@ -67,6 +78,7 @@ |
185 | |
186 | Rectangle { |
187 | id: loadingOverlay |
188 | + objectName: "loadingOverlay" |
189 | opacity: 0.7 |
190 | color: "white" |
191 | visible: false |
192 | |
193 | === modified file 'online-accounts-provider/NewAccount.qml' |
194 | --- online-accounts-provider/NewAccount.qml 2013-09-13 19:28:05 +0000 |
195 | +++ online-accounts-provider/NewAccount.qml 2013-10-04 19:17:45 +0000 |
196 | @@ -55,6 +55,7 @@ |
197 | |
198 | Label { |
199 | id: errorLabel |
200 | + objectName: "errorLabel" |
201 | text: "" |
202 | font.bold: true |
203 | color: "red" |
204 | @@ -75,6 +76,7 @@ |
205 | |
206 | TextField { |
207 | id: emailTextField |
208 | + objectName: "emailTextField" |
209 | placeholderText: "Your email" |
210 | width: main.width - (2 * main.anchors.margins) |
211 | anchors.left: parent.left |
212 | @@ -83,6 +85,7 @@ |
213 | focus: true |
214 | KeyNavigation.tab: loginForm.visible ? loginForm.passwordTextField : registerForm.nameTextField |
215 | KeyNavigation.backtab: loginForm.visible ? ( loginForm.twoFactorVisible ? loginForm.twoFactorTextField : loginForm.passwordTextField) : registerForm.confirmPasswordTextField |
216 | + inputMethodHints: Qt.ImhEmailCharactersOnly |
217 | } |
218 | |
219 | Row { |
220 | @@ -93,6 +96,7 @@ |
221 | |
222 | Switch { |
223 | id: newUserToggleSwitch |
224 | + objectName: "newUserToggleSwitch" |
225 | checked: false |
226 | |
227 | onCheckedChanged: { |
228 | @@ -196,6 +200,7 @@ |
229 | immediately. |
230 | */ |
231 | function processForm() { |
232 | + Qt.inputMethod.hide(); |
233 | loadingOverlay.visible = true; |
234 | formSubmitTimer.running = true; |
235 | } |
236 | @@ -249,6 +254,7 @@ |
237 | } |
238 | |
239 | function validateInput() { |
240 | + console.debug("in validateInput, emailTextField.text = " + emailTextField.text); |
241 | formValid = emailTextField.acceptableInput; |
242 | if(!formValid) { |
243 | showError("Please enter a valid email address."); |
244 | |
245 | === modified file 'online-accounts-provider/RegisterForm.qml' |
246 | --- online-accounts-provider/RegisterForm.qml 2013-09-13 18:31:34 +0000 |
247 | +++ online-accounts-provider/RegisterForm.qml 2013-10-04 19:17:45 +0000 |
248 | @@ -19,6 +19,7 @@ |
249 | |
250 | TextField { |
251 | id: nameTextField |
252 | + objectName: "nameTextField" |
253 | placeholderText: "Your name" |
254 | width: main.width - (2 * main.anchors.margins) |
255 | KeyNavigation.tab: passwordTextField |
256 | @@ -27,26 +28,31 @@ |
257 | |
258 | TextField { |
259 | id: passwordTextField |
260 | + objectName: "passwordTextField" |
261 | placeholderText: "Password with at least 8 characters" |
262 | echoMode: TextInput.Password |
263 | width: main.width - (2 * main.anchors.margins) |
264 | KeyNavigation.tab: confirmPasswordTextField |
265 | KeyNavigation.backtab: nameTextField |
266 | + inputMethodHints: Qt.ImhSensitiveData |
267 | } |
268 | |
269 | TextField { |
270 | id: confirmPasswordTextField |
271 | + objectName: "confirmPasswordTextField" |
272 | placeholderText: "Re-type password" |
273 | echoMode: TextInput.Password |
274 | width: main.width - (2 * main.anchors.margins) |
275 | KeyNavigation.tab: emailTextField /* from main */ |
276 | KeyNavigation.backtab: passwordTextField |
277 | + inputMethodHints: Qt.ImhSensitiveData |
278 | } |
279 | |
280 | Row { |
281 | spacing: units.gu(2) |
282 | CheckBox { |
283 | id: termsAndConditionsCheckBox |
284 | + objectName: "termsAndConditionsCheckBox" |
285 | checked: false |
286 | } |
287 | |
288 | @@ -58,6 +64,7 @@ |
289 | } |
290 | |
291 | ButtonRow { |
292 | + objectName: "buttonRow-RegisterForm" |
293 | anchors.left: parent.left |
294 | anchors.right: parent.right |
295 | } |
296 | |
297 | === added directory 'online-accounts-provider/tests' |
298 | === added file 'online-accounts-provider/tests/CMakeLists.txt' |
299 | --- online-accounts-provider/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
300 | +++ online-accounts-provider/tests/CMakeLists.txt 2013-10-04 19:17:45 +0000 |
301 | @@ -0,0 +1,10 @@ |
302 | +SET (TESTS_TARGET test-online-accounts-provider) |
303 | + |
304 | +add_custom_target(online-accounts-provider-autopilot-tests |
305 | + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/autopilot/run ${CMAKE_CURRENT_BINARY_DIR} |
306 | + DEPENDS ${QML_PLUGIN_NAME} |
307 | +) |
308 | + |
309 | +add_custom_target(online-accounts-provider-qmlunit-tests |
310 | + COMMAND qmltestrunner -input ${CMAKE_CURRENT_SOURCE_DIR}/unit |
311 | +) |
312 | |
313 | === added directory 'online-accounts-provider/tests/autopilot' |
314 | === added file 'online-accounts-provider/tests/autopilot/TestWrapperExisting.qml' |
315 | --- online-accounts-provider/tests/autopilot/TestWrapperExisting.qml 1970-01-01 00:00:00 +0000 |
316 | +++ online-accounts-provider/tests/autopilot/TestWrapperExisting.qml 2013-10-04 19:17:45 +0000 |
317 | @@ -0,0 +1,42 @@ |
318 | +import QtQuick 2.0 |
319 | +import Ubuntu.Components 0.1 |
320 | +import Ubuntu.OnlineAccounts 0.1 |
321 | +import UbuntuOne 1.0 |
322 | + |
323 | + |
324 | +MainView { |
325 | + |
326 | + objectName: "mainView" |
327 | + |
328 | + applicationName: "Ubuntu One UOA Provider Plugin Tester" |
329 | + |
330 | + width: units.gu(100) |
331 | + height: units.gu(100) |
332 | + |
333 | + Page { |
334 | + title: "testing" |
335 | + objectName: "testingPage" |
336 | + |
337 | + Rectangle { |
338 | + id: fakeAccount |
339 | + objectName: "FakeExistingUOAAccount" |
340 | + property var accountId: 47 |
341 | + signal synced |
342 | + |
343 | + property string displayName: "my@email.com" |
344 | + function remove(){ |
345 | + } |
346 | + } |
347 | + |
348 | + Loader { |
349 | + id: loader |
350 | + property var account: fakeAccount |
351 | + |
352 | + anchors.fill: parent |
353 | + |
354 | + source: "../../Main.qml" |
355 | + |
356 | + } |
357 | + |
358 | + } |
359 | +} |
360 | \ No newline at end of file |
361 | |
362 | === added file 'online-accounts-provider/tests/autopilot/TestWrapperNew.qml' |
363 | --- online-accounts-provider/tests/autopilot/TestWrapperNew.qml 1970-01-01 00:00:00 +0000 |
364 | +++ online-accounts-provider/tests/autopilot/TestWrapperNew.qml 2013-10-04 19:17:45 +0000 |
365 | @@ -0,0 +1,48 @@ |
366 | +import QtQuick 2.0 |
367 | +import Ubuntu.Components 0.1 |
368 | +import Ubuntu.OnlineAccounts 0.1 |
369 | +import UbuntuOne 1.0 |
370 | + |
371 | + |
372 | +MainView { |
373 | + |
374 | + objectName: "mainView" |
375 | + |
376 | + applicationName: "Ubuntu One UOA Provider Plugin Tester" |
377 | + |
378 | + width: units.gu(100) |
379 | + height: units.gu(100) |
380 | + |
381 | + Page { |
382 | + title: "testing" |
383 | + id: testingPage |
384 | + objectName: "testingPage" |
385 | + |
386 | + Rectangle { |
387 | + id: fakeAccount |
388 | + objectName: "FakeNewUOAAccount" |
389 | + property var accountId: 0 |
390 | + signal synced |
391 | + |
392 | + property string displayName: "" |
393 | + function sync() { |
394 | + } |
395 | + |
396 | + /* fake to avoid creating a UOA account */ |
397 | + property var objectHandle: Qt.createQmlObject('import QtQuick 2.0; Rectangle {}', |
398 | + testingPage, |
399 | + "dynamically-created-fakerect"); |
400 | + } |
401 | + |
402 | + Loader { |
403 | + id: loader |
404 | + property var account: fakeAccount |
405 | + |
406 | + anchors.fill: parent |
407 | + |
408 | + source: "../../Main.qml" |
409 | + |
410 | + } |
411 | + |
412 | + } |
413 | +} |
414 | \ No newline at end of file |
415 | |
416 | === added directory 'online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests' |
417 | === added file 'online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/__init__.py' |
418 | --- online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/__init__.py 1970-01-01 00:00:00 +0000 |
419 | +++ online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/__init__.py 2013-10-04 19:17:45 +0000 |
420 | @@ -0,0 +1,124 @@ |
421 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
422 | + |
423 | +"""UbuntuOne Credentials Online-Accounts provider plugin autopilot tests.""" |
424 | + |
425 | +from os import remove |
426 | +import os.path |
427 | +from tempfile import mktemp |
428 | +import subprocess |
429 | + |
430 | +from autopilot.input import Mouse, Touch, Pointer |
431 | +from autopilot.matchers import Eventually |
432 | +from autopilot.platform import model |
433 | +from testtools.matchers import Is, Not, Equals |
434 | +from autopilot.testcase import AutopilotTestCase |
435 | + |
436 | + |
437 | +def get_module_include_path(): |
438 | + return os.path.abspath( |
439 | + os.path.join( |
440 | + os.path.dirname(__file__), |
441 | + '..', |
442 | + '..', |
443 | + '..', |
444 | + '..', |
445 | + 'modules') |
446 | + ) |
447 | + |
448 | + |
449 | +class UbuntuTouchAppTestCase(AutopilotTestCase): |
450 | + """Provides several useful methods for the tests.""" |
451 | + |
452 | + if model() == 'Desktop': |
453 | + scenarios = [ |
454 | + ('with mouse', dict(input_device_class=Mouse)) |
455 | + ] |
456 | + else: |
457 | + scenarios = [ |
458 | + ('with touch', dict(input_device_class=Touch)) |
459 | + ] |
460 | + |
461 | + @property |
462 | + def main_window(self): |
463 | + return MainWindow(self.app) |
464 | + |
465 | + def setUp(self): |
466 | + self.pointing_device = Pointer(self.input_device_class.create()) |
467 | + super(UbuntuTouchAppTestCase, self).setUp() |
468 | + self.launch_test_qml() |
469 | + |
470 | + def launch_test_qml(self): |
471 | + # If the test class has defined a 'test_qml' class attribute then we |
472 | + # write it to disk and launch it inside the QML Scene. If not, then we |
473 | + # silently do nothing (presumably the test has something else planned). |
474 | + arch = subprocess.check_output(["dpkg-architecture", |
475 | + "-qDEB_HOST_MULTIARCH"]).strip() |
476 | + |
477 | + if hasattr(self, 'test_qml') and isinstance(self.test_qml, basestring): |
478 | + qml_path = mktemp(suffix='.qml') |
479 | + open(qml_path, 'w').write(self.test_qml) |
480 | + self.addCleanup(remove, qml_path) |
481 | + |
482 | + self.app = self.launch_test_application( |
483 | + "/usr/lib/" + arch + "/qt5/bin/qmlscene", |
484 | + "-I", get_module_include_path(), |
485 | + qml_path, |
486 | + app_type='qt') |
487 | + |
488 | + if hasattr(self, 'test_qml_file') and isinstance(self.test_qml_file, basestring): |
489 | + qml_path = self.test_qml_file |
490 | + self.app = self.launch_test_application( |
491 | + "/usr/lib/" + arch + "/qt5/bin/qmlscene", |
492 | + "-I", get_module_include_path(), |
493 | + qml_path, |
494 | + app_type='qt') |
495 | + |
496 | + self.assertThat(self.get_qml_view().visible, Eventually(Equals(True))) |
497 | + |
498 | + def get_qml_view(self): |
499 | + """Get the main QML view""" |
500 | + |
501 | + return self.app.select_single("QQuickView") |
502 | + |
503 | + def get_mainview(self): |
504 | + """Get the QML MainView""" |
505 | + |
506 | + mainView = self.app.select_single("MainView") |
507 | + self.assertThat(mainView, Not(Is(None))) |
508 | + return mainView |
509 | + |
510 | + def get_object(self, objectName): |
511 | + """Get a object based on the objectName""" |
512 | + |
513 | + obj = self.app.select_single(objectName=objectName) |
514 | + self.assertThat(obj, Not(Is(None))) |
515 | + return obj |
516 | + |
517 | + def mouse_click(self, objectName): |
518 | + """Move mouse on top of the object and click on it""" |
519 | + |
520 | + obj = self.get_object(objectName) |
521 | + self.pointing_device.move_to_object(obj) |
522 | + self.pointing_device.click() |
523 | + |
524 | + def mouse_press(self, objectName): |
525 | + """Move mouse on top of the object and press and hold mouse button""" |
526 | + |
527 | + obj = self.get_object(objectName) |
528 | + self.pointing_device.move_to_object(obj) |
529 | + self.pointing_device.press() |
530 | + |
531 | + def mouse_release(self): |
532 | + """Release mouse button""" |
533 | + |
534 | + self.pointing_device.release() |
535 | + |
536 | + def type_string(self, string): |
537 | + """Type a string with keyboard""" |
538 | + |
539 | + self.keyboard.type(string) |
540 | + |
541 | + def type_key(self, key): |
542 | + """Type a single key with keyboard""" |
543 | + |
544 | + self.keyboard.key(key) |
545 | |
546 | === added directory 'online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main' |
547 | === added file 'online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/__init__.py' |
548 | --- online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/__init__.py 1970-01-01 00:00:00 +0000 |
549 | +++ online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/__init__.py 2013-10-04 19:17:45 +0000 |
550 | @@ -0,0 +1,1 @@ |
551 | +""" A Generic test suite """ |
552 | |
553 | === added file 'online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/test_main.py' |
554 | --- online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/test_main.py 1970-01-01 00:00:00 +0000 |
555 | +++ online-accounts-provider/tests/autopilot/UbuntuOneCredentialsProviderAutopilotTests/main/test_main.py 2013-10-04 19:17:45 +0000 |
556 | @@ -0,0 +1,144 @@ |
557 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
558 | + |
559 | +"""Tests for launching the plugin""" |
560 | + |
561 | +from autopilot.matchers import Eventually |
562 | +from testtools.matchers import Equals |
563 | +import os |
564 | +from UbuntuOneCredentialsProviderAutopilotTests import UbuntuTouchAppTestCase |
565 | + |
566 | + |
567 | +class NewUOAAccountTests(UbuntuTouchAppTestCase): |
568 | + |
569 | + test_qml_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), |
570 | + "../../") |
571 | + test_qml_filename = "TestWrapperNew.qml" |
572 | + test_qml_file = os.path.join(test_qml_path, test_qml_filename) |
573 | + |
574 | + def setUp(self): |
575 | + super(NewUOAAccountTests, self).setUp() |
576 | + self.uoa_account = self.get_object(objectName="FakeNewUOAAccount") |
577 | + |
578 | + def test_select_mainView(self): |
579 | + mainView = self.get_mainview() |
580 | + self.assertThat(mainView.visible, Eventually(Equals(True))) |
581 | + |
582 | + def test_loadingOverlay_starts_invisible(self): |
583 | + overlay = self.get_object(objectName="loadingOverlay") |
584 | + self.assertThat(overlay.visible, Eventually(Equals(False))) |
585 | + |
586 | + def test_email_field_visible_focused(self): |
587 | + emailTextField = self.get_object(objectName="emailTextField") |
588 | + self.assertThat(emailTextField.visible, Eventually(Equals(True))) |
589 | + self.assertThat(emailTextField.focus, Eventually(Equals(True))) |
590 | + |
591 | + def test_login_initial_state(self): |
592 | + passwordTextField = self.get_object("loginFormPasswordTextField") |
593 | + self.assertThat(passwordTextField.visible, Eventually(Equals(True))) |
594 | + twoFactorTextField = self.get_object(objectName="twoFactorTextField") |
595 | + self.assertThat(twoFactorTextField.visible, Eventually(Equals(False))) |
596 | + |
597 | + def test_switch_to_newuser(self): |
598 | + |
599 | + self.mouse_click(objectName="newUserToggleSwitch") |
600 | + |
601 | + passwordField = self.get_object("loginFormPasswordTextField") |
602 | + self.assertThat(passwordField.visible, Eventually(Equals(False))) |
603 | + |
604 | + nameTextField = self.get_object("nameTextField") |
605 | + self.assertThat(nameTextField.visible, Eventually(Equals(True))) |
606 | + |
607 | + def click_continuebutton_from(self, parentObjectName): |
608 | + parent = self.get_object(parentObjectName) |
609 | + continueButton = parent.select_single(objectName="continueButton") |
610 | + self.pointing_device.move_to_object(continueButton) |
611 | + self.pointing_device.click() |
612 | + |
613 | + def test_login_error_on_no_input(self): |
614 | + errorTextField = self.get_object("errorLabel") |
615 | + self.assertThat(errorTextField.visible, Eventually(Equals(False))) |
616 | + self.click_continuebutton_from("buttonRow-LoginForm-noTwoFactor") |
617 | + self.assertThat(errorTextField.visible, Eventually(Equals(True))) |
618 | + |
619 | + def test_login_error_on_bad_email(self): |
620 | + errorTextField = self.get_object("errorLabel") |
621 | + self.assertThat(errorTextField.visible, Eventually(Equals(False))) |
622 | + self.mouse_click("emailTextField") |
623 | + self.type_string("this isn't a valid email") |
624 | + |
625 | + self.click_continuebutton_from("buttonRow-LoginForm-noTwoFactor") |
626 | + self.assertThat(errorTextField.visible, Eventually(Equals(True))) |
627 | + |
628 | + def _setup_newuser_errors(self): |
629 | + self.emailTextField = self.get_object("emailTextField") |
630 | + self.mouse_click("emailTextField") |
631 | + self.type_string("valid@email.com") |
632 | + self.assertThat(self.emailTextField.acceptableInput, |
633 | + Eventually(Equals(True))) |
634 | + self.errorTextField = self.get_object("errorLabel") |
635 | + self.mouse_click(objectName="newUserToggleSwitch") |
636 | + |
637 | + def test_newuser_error_on_no_name(self): |
638 | + self._setup_newuser_errors() |
639 | + self.click_continuebutton_from("buttonRow-RegisterForm") |
640 | + self.assertThat(self.errorTextField.visible, Eventually(Equals(True))) |
641 | + |
642 | + def test_newuser_error_on_no_password(self): |
643 | + self._setup_newuser_errors() |
644 | + self.mouse_click("nameTextField") |
645 | + self.type_string("A Name") |
646 | + self.click_continuebutton_from("buttonRow-RegisterForm") |
647 | + self.assertThat(self.errorTextField.visible, Eventually(Equals(True))) |
648 | + |
649 | + def test_newuser_error_on_no_password_match(self): |
650 | + self._setup_newuser_errors() |
651 | + self.mouse_click("nameTextField") |
652 | + self.type_string("A Name") |
653 | + |
654 | + self.mouse_click("passwordTextField") |
655 | + self.type_string("12345678910111213141516") |
656 | + self.mouse_click("confirmPasswordTextField") |
657 | + self.type_string("123456789ABCDEF") |
658 | + self.mouse_click(objectName="termsAndConditionsCheckBox") |
659 | + self.click_continuebutton_from("buttonRow-RegisterForm") |
660 | + self.assertThat(self.errorTextField.visible, Eventually(Equals(True))) |
661 | + |
662 | + def test_newuser_error_on_short_password(self): |
663 | + self._setup_newuser_errors() |
664 | + self.mouse_click("nameTextField") |
665 | + self.type_string("A Name") |
666 | + self.mouse_click("passwordTextField") |
667 | + self.type_string("123") |
668 | + self.mouse_click("confirmPasswordTextField") |
669 | + self.type_string("123") |
670 | + self.mouse_click(objectName="termsAndConditionsCheckBox") |
671 | + self.click_continuebutton_from("buttonRow-RegisterForm") |
672 | + self.assertThat(self.errorTextField.visible, Eventually(Equals(True))) |
673 | + |
674 | + |
675 | +class ExistingUOAAccountTests(UbuntuTouchAppTestCase): |
676 | + |
677 | + test_qml_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), |
678 | + "../../") |
679 | + test_qml_filename = "TestWrapperExisting.qml" |
680 | + test_qml_file = os.path.join(test_qml_path, test_qml_filename) |
681 | + |
682 | + def setUp(self): |
683 | + super(ExistingUOAAccountTests, self).setUp() |
684 | + self.uoa_account = self.get_object(objectName="FakeExistingUOAAccount") |
685 | + |
686 | + def test_show_remove_account_dialog(self): |
687 | + |
688 | + self.mouse_click(objectName="removeAccountButton") |
689 | + |
690 | + confirmRemoveButton = self.get_object("confirmRemoveAccountButton") |
691 | + |
692 | + self.assertThat(confirmRemoveButton.visible, |
693 | + Eventually(Equals(True))) |
694 | + |
695 | + self.mouse_click(objectName="cancelRemoveAccountButton") |
696 | + |
697 | + def test_shows_expected_email(self): |
698 | + emailListItem = self.get_object("emailListItem") |
699 | + self.assertThat(emailListItem.value, |
700 | + Eventually(Equals("my@email.com"))) |
701 | |
702 | === added file 'online-accounts-provider/tests/autopilot/run' |
703 | --- online-accounts-provider/tests/autopilot/run 1970-01-01 00:00:00 +0000 |
704 | +++ online-accounts-provider/tests/autopilot/run 2013-10-04 19:17:45 +0000 |
705 | @@ -0,0 +1,12 @@ |
706 | +#!/bin/bash |
707 | + |
708 | +if [[ -z `which autopilot` ]]; then |
709 | + echo "Autopilot is not installed. Skip" |
710 | + exit |
711 | +fi |
712 | + |
713 | +SCRIPTPATH=`dirname $0` |
714 | +pushd ${SCRIPTPATH} |
715 | +export QML2_IMPORT_PATH=/usr/lib/i386-linux-gnu/ubuntu-system-settings/private:$1/../../qml-credentials-service |
716 | +autopilot run UbuntuOneCredentialsProviderAutopilotTests |
717 | +popd |
718 | |
719 | === modified file 'qml-credentials-service/CMakeLists.txt' |
720 | --- qml-credentials-service/CMakeLists.txt 2013-08-21 20:49:46 +0000 |
721 | +++ qml-credentials-service/CMakeLists.txt 2013-10-04 19:17:45 +0000 |
722 | @@ -23,3 +23,6 @@ |
723 | ) |
724 | |
725 | install (CODE "execute_process(COMMAND qmlplugindump ${QML_MODULE_NAME} ${QML_PLUGIN_API_VERSION} ${CMAKE_INSTALL_PREFIX}/${QML_MODULE_INSTALL_DIR} OUTPUT_FILE ${CMAKE_INSTALL_PREFIX}/${QML_MODULE_INSTALL_DIR}/${QML_MODULE_NAME}/${QML_MODULE_NAME}.qmltypes)") |
726 | + |
727 | +add_custom_command(TARGET ${QML_PLUGIN_NAME} POST_BUILD |
728 | + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_BINARY_DIR} ${QML_MODULE_NAME}) |
729 | \ No newline at end of file |
730 | |
731 | === modified file 'qml-credentials-service/ubuntuone_credentials_service.cpp' |
732 | --- qml-credentials-service/ubuntuone_credentials_service.cpp 2013-08-26 18:42:47 +0000 |
733 | +++ qml-credentials-service/ubuntuone_credentials_service.cpp 2013-10-04 19:17:45 +0000 |
734 | @@ -1,4 +1,5 @@ |
735 | #include "ubuntuone_credentials_service.h" |
736 | +#include "errormessages.h" |
737 | #include <QDebug> |
738 | |
739 | UbuntuOneCredentialsService::UbuntuOneCredentialsService(QQuickItem *parent): |
740 | @@ -153,5 +154,9 @@ |
741 | void UbuntuOneCredentialsService::handleError(const ErrorResponse& error) |
742 | { |
743 | _state = IDLE; |
744 | - emit loginOrRegisterError(error.message()); |
745 | + if (error.httpStatus() == 0 || error.httpReason() == NO_HTTP_REASON) { |
746 | + emit loginOrRegisterError("Network error - please retry."); |
747 | + } else { |
748 | + emit loginOrRegisterError(error.message()); |
749 | + } |
750 | } |