Merge lp:~diegosarmentero/pay-ui/pay-errors into lp:pay-ui
- pay-errors
- Merge into first-branch
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | dobey | ||||
Approved revision: | 7 | ||||
Merged at revision: | 5 | ||||
Proposed branch: | lp:~diegosarmentero/pay-ui/pay-errors | ||||
Merge into: | lp:pay-ui | ||||
Diff against target: |
495 lines (+158/-23) 11 files modified
app/payui.qml (+76/-14) app/ui/CheckoutPage.qml (+22/-1) app/ui/DirectPurchase.qml (+19/-0) app/ui/UbuntuPurchaseWebkit.qml (+1/-5) backend/modules/payui/network.cpp (+6/-0) backend/modules/payui/network.h (+1/-0) backend/modules/payui/purchase.cpp (+11/-1) backend/modules/payui/purchase.h (+2/-0) backend/tests/mock_click_server.py (+8/-0) backend/tests/test_network.cpp (+11/-1) manifest.json (+1/-1) |
||||
To merge this branch: | bzr merge lp:~diegosarmentero/pay-ui/pay-errors | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alejandro J. Cura (community) | Approve | ||
dobey (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+225397@code.launchpad.net |
Commit message
- Showing errors and give the user the chance to recover from them.
- Improve logging
Description of the change
Not quit on any error, but instead show a message to the user, and let the user decide the action to follow.
PS Jenkins bot (ps-jenkins) wrote : | # |
Alejandro J. Cura (alecu) wrote : | # |
Please commit this branch with --fixes lp:1333394
Why are there no unit tests for the qml bits?
- 7. By Diego Sarmentero
-
linking bug
Diego Sarmentero (diegosarmentero) wrote : | # |
> Please commit this branch with --fixes lp:1333394
Done
>
> Why are there no unit tests for the qml bits?
As I mentioned yesterday, we can't do qml tests YET, because we need to load the Purchase plugin, and there is a bug with autopilot which I already mentioned to elopio and he confirmed it that for some reason is breaking autopilot on loading those qml plugins.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:7
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alejandro J. Cura (alecu) wrote : | # |
On Thu, Jul 3, 2014 at 8:29 AM, Diego Sarmentero
<email address hidden> wrote:
>> Please commit this branch with --fixes lp:1333394
>
> Done
>
>>
>> Why are there no unit tests for the qml bits?
>
> As I mentioned yesterday, we can't do qml tests YET, because we need to load the Purchase plugin, and there is a bug with autopilot which I already mentioned to elopio and he confirmed it that for some reason is breaking autopilot on loading those qml plugins.
Please link here the autopilot bug, and please open a new bug for the
missing tests in pay-ui.
Diego Sarmentero (diegosarmentero) wrote : | # |
> Please commit this branch with --fixes lp:1333394
>
> Why are there no unit tests for the qml bits?
Bug created for this: https:/
dobey (dobey) : | # |
Alejandro J. Cura (alecu) wrote : | # |
Code looks good, and tested on mako, seems to be working ok.
Preview Diff
1 | === modified file 'app/payui.qml' | |||
2 | --- app/payui.qml 2014-06-25 20:58:29 +0000 | |||
3 | +++ app/payui.qml 2014-07-03 11:28:29 +0000 | |||
4 | @@ -6,9 +6,12 @@ | |||
5 | 6 | import "ui" | 6 | import "ui" |
6 | 7 | 7 | ||
7 | 8 | /*! | 8 | /*! |
11 | 9 | \brief MainView with Tabs element. | 9 | states: |
12 | 10 | First Tab has a single Label and | 10 | - add-payment |
13 | 11 | second Tab has a single ToolbarAction. | 11 | - direct |
14 | 12 | - buy-interaction | ||
15 | 13 | - checkout | ||
16 | 14 | - no-credentials | ||
17 | 12 | */ | 15 | */ |
18 | 13 | 16 | ||
19 | 14 | MainView { | 17 | MainView { |
20 | @@ -32,6 +35,8 @@ | |||
21 | 32 | 35 | ||
22 | 33 | property bool loading: true | 36 | property bool loading: true |
23 | 34 | property bool purchasing: false | 37 | property bool purchasing: false |
24 | 38 | property string errorTitle: "" | ||
25 | 39 | property string errorMessage: "" | ||
26 | 35 | 40 | ||
27 | 36 | 41 | ||
28 | 37 | AccountServiceModel { | 42 | AccountServiceModel { |
29 | @@ -55,8 +60,10 @@ | |||
30 | 55 | if (payments.length == 0) { | 60 | if (payments.length == 0) { |
31 | 56 | webkit.title = i18n.tr("Add Payment"); | 61 | webkit.title = i18n.tr("Add Payment"); |
32 | 57 | webkit.url = purchase.getAddPaymentUrl(); | 62 | webkit.url = purchase.getAddPaymentUrl(); |
33 | 63 | mainView.state = "add-payment"; | ||
34 | 58 | pageStack.push(webkit); | 64 | pageStack.push(webkit); |
35 | 59 | } else { | 65 | } else { |
36 | 66 | mainView.state = "direct"; | ||
37 | 60 | pageStack.push(direct); | 67 | pageStack.push(direct); |
38 | 61 | } | 68 | } |
39 | 62 | hideLoading(); | 69 | hideLoading(); |
40 | @@ -65,26 +72,37 @@ | |||
41 | 65 | onBuyItemFailed: { | 72 | onBuyItemFailed: { |
42 | 66 | mainView.purchasing = false; | 73 | mainView.purchasing = false; |
43 | 67 | hideLoading(); | 74 | hideLoading(); |
45 | 68 | purchase.quitCancel(); | 75 | var title = i18n.tr("Purchase failed"); |
46 | 76 | var message = i18n.tr("The purchase couldn't be completed."); | ||
47 | 77 | mainView.showErrorDialog(title, message); | ||
48 | 69 | } | 78 | } |
49 | 70 | 79 | ||
50 | 71 | onBuyItemSucceeded: { | 80 | onBuyItemSucceeded: { |
52 | 72 | Qt.quit(); | 81 | purchase.quitSuccess(); |
53 | 73 | } | 82 | } |
54 | 74 | 83 | ||
55 | 75 | onBuyInterationRequired: { | 84 | onBuyInterationRequired: { |
56 | 76 | mainView.purchasing = false; | 85 | mainView.purchasing = false; |
57 | 77 | webkit.title = ""; | 86 | webkit.title = ""; |
58 | 78 | webkit.url = url; | 87 | webkit.url = url; |
59 | 88 | mainView.state = "buy-interaction"; | ||
60 | 79 | pageStack.push(webkit); | 89 | pageStack.push(webkit); |
61 | 80 | } | 90 | } |
62 | 81 | 91 | ||
63 | 82 | onError: { | 92 | onError: { |
66 | 83 | purchase.quitCancel(); | 93 | hideLoading(); |
67 | 84 | hideLoading(); | 94 | var title = i18n.tr("Error contacting the server"); |
68 | 95 | var message = i18n.tr("Do you want to try again?"); | ||
69 | 96 | mainView.showErrorDialog(title, message); | ||
70 | 97 | } | ||
71 | 98 | |||
72 | 99 | onAuthenticationError: { | ||
73 | 100 | hideLoading(); | ||
74 | 101 | pageStack.currentPage.showWrongPassword(); | ||
75 | 85 | } | 102 | } |
76 | 86 | 103 | ||
77 | 87 | onCredentialsNotFound: { | 104 | onCredentialsNotFound: { |
78 | 105 | mainView.state = "no-credentials"; | ||
79 | 88 | pageStack.push(noCredentials); | 106 | pageStack.push(noCredentials); |
80 | 89 | hideLoading(); | 107 | hideLoading(); |
81 | 90 | } | 108 | } |
82 | @@ -99,6 +117,12 @@ | |||
83 | 99 | mainView.loading = false; | 117 | mainView.loading = false; |
84 | 100 | } | 118 | } |
85 | 101 | 119 | ||
86 | 120 | function showErrorDialog(title, message) { | ||
87 | 121 | mainView.errorTitle = title; | ||
88 | 122 | mainView.errorMessage = message; | ||
89 | 123 | PopupUtils.open(errorDialogContainer); | ||
90 | 124 | } | ||
91 | 125 | |||
92 | 102 | Component { | 126 | Component { |
93 | 103 | id: loadingDialogContainer | 127 | id: loadingDialogContainer |
94 | 104 | Dialog { | 128 | Dialog { |
95 | @@ -127,6 +151,33 @@ | |||
96 | 127 | } | 151 | } |
97 | 128 | } | 152 | } |
98 | 129 | 153 | ||
99 | 154 | Component { | ||
100 | 155 | id: errorDialogContainer | ||
101 | 156 | Dialog { | ||
102 | 157 | id: errorDialog | ||
103 | 158 | title: mainView.errorTitle | ||
104 | 159 | text: mainView.errorMessage | ||
105 | 160 | |||
106 | 161 | Button { | ||
107 | 162 | text: i18n.tr("Retry") | ||
108 | 163 | color: UbuntuColors.orange | ||
109 | 164 | onClicked: { | ||
110 | 165 | showLoading(); | ||
111 | 166 | purchase.checkCredentials(); | ||
112 | 167 | PopupUtils.close(errorDialog); | ||
113 | 168 | } | ||
114 | 169 | } | ||
115 | 170 | Button { | ||
116 | 171 | text: i18n.tr("Exit") | ||
117 | 172 | color: UbuntuColors.coolGrey | ||
118 | 173 | onClicked: { | ||
119 | 174 | PopupUtils.close(errorDialog); | ||
120 | 175 | purchase.quitCancel(); | ||
121 | 176 | } | ||
122 | 177 | } | ||
123 | 178 | } | ||
124 | 179 | } | ||
125 | 180 | |||
126 | 130 | PageStack { | 181 | PageStack { |
127 | 131 | id: pageStack | 182 | id: pageStack |
128 | 132 | Component.onCompleted: { | 183 | Component.onCompleted: { |
129 | @@ -140,6 +191,7 @@ | |||
130 | 140 | account: accounts | 191 | account: accounts |
131 | 141 | 192 | ||
132 | 142 | onShowPaymentTypes: { | 193 | onShowPaymentTypes: { |
133 | 194 | mainView.state = "checkout"; | ||
134 | 143 | pageStack.push(checkout); | 195 | pageStack.push(checkout); |
135 | 144 | } | 196 | } |
136 | 145 | 197 | ||
137 | @@ -172,6 +224,7 @@ | |||
138 | 172 | onAddCreditCard: { | 224 | onAddCreditCard: { |
139 | 173 | webkit.title = i18n.tr("Add Payment"); | 225 | webkit.title = i18n.tr("Add Payment"); |
140 | 174 | webkit.url = purchase.getAddPaymentUrl(); | 226 | webkit.url = purchase.getAddPaymentUrl(); |
141 | 227 | mainView.state = "add-payment"; | ||
142 | 175 | pageStack.push(webkit); | 228 | pageStack.push(webkit); |
143 | 176 | } | 229 | } |
144 | 177 | } | 230 | } |
145 | @@ -180,16 +233,25 @@ | |||
146 | 180 | id: webkit | 233 | id: webkit |
147 | 181 | visible: false | 234 | visible: false |
148 | 182 | 235 | ||
149 | 183 | onPayTypeAdded: { | ||
150 | 184 | showLoading(); | ||
151 | 185 | purchase.getPaymentTypes(); | ||
152 | 186 | pageStack.push(checkout); | ||
153 | 187 | } | ||
154 | 188 | onPurchaseCanceled: { | 236 | onPurchaseCanceled: { |
156 | 189 | purchase.quitCancel(); | 237 | hideLoading(); |
157 | 238 | if (mainView.state == "add-payment") { | ||
158 | 239 | var title = i18n.tr("Adding Credit Card failed"); | ||
159 | 240 | var message = i18n.tr("Do you want to try again?"); | ||
160 | 241 | mainView.showErrorDialog(title, message); | ||
161 | 242 | } else { | ||
162 | 243 | var title = i18n.tr("Purchase failed"); | ||
163 | 244 | var message = i18n.tr("The purchase couldn't be completed."); | ||
164 | 245 | mainView.showErrorDialog(title, message); | ||
165 | 246 | } | ||
166 | 190 | } | 247 | } |
167 | 191 | onPurchaseSucceeded: { | 248 | onPurchaseSucceeded: { |
169 | 192 | pageStack.push(success); | 249 | if (mainView.state == "add-payment") { |
170 | 250 | showLoading(); | ||
171 | 251 | purchase.getPaymentTypes(); | ||
172 | 252 | } else { | ||
173 | 253 | purchase.quitSuccess(); | ||
174 | 254 | } | ||
175 | 193 | } | 255 | } |
176 | 194 | 256 | ||
177 | 195 | onLoading: { | 257 | onLoading: { |
178 | 196 | 258 | ||
179 | === modified file 'app/ui/CheckoutPage.qml' | |||
180 | --- app/ui/CheckoutPage.qml 2014-06-25 20:58:29 +0000 | |||
181 | +++ app/ui/CheckoutPage.qml 2014-07-03 11:28:29 +0000 | |||
182 | @@ -24,6 +24,7 @@ | |||
183 | 24 | 24 | ||
184 | 25 | title: selector.currentlyExpanded ? i18n.tr("Payment type") : i18n.tr("Checkout") | 25 | title: selector.currentlyExpanded ? i18n.tr("Payment type") : i18n.tr("Checkout") |
185 | 26 | 26 | ||
186 | 27 | property bool _errorVisible: false | ||
187 | 27 | property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0 | 28 | property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0 |
188 | 28 | property alias itemTitle: titleLabel.text | 29 | property alias itemTitle: titleLabel.text |
189 | 29 | property alias itemSubtitle: subtitleLabel.text | 30 | property alias itemSubtitle: subtitleLabel.text |
190 | @@ -37,11 +38,16 @@ | |||
191 | 37 | signal addCreditCard | 38 | signal addCreditCard |
192 | 38 | 39 | ||
193 | 39 | function launchPurchase() { | 40 | function launchPurchase() { |
194 | 41 | pageCheckout._errorVisible = false; | ||
195 | 40 | var pay = selector.model[selector.selectedIndex]; | 42 | var pay = selector.model[selector.selectedIndex]; |
196 | 41 | var email = accountView.currentItem.email; | 43 | var email = accountView.currentItem.email; |
197 | 42 | pageCheckout.buy(email, passwordField.text, pay.paymentId, pay.backendId); | 44 | pageCheckout.buy(email, passwordField.text, pay.paymentId, pay.backendId); |
198 | 43 | } | 45 | } |
199 | 44 | 46 | ||
200 | 47 | function showWrongPassword() { | ||
201 | 48 | pageCheckout._errorVisible = true; | ||
202 | 49 | } | ||
203 | 50 | |||
204 | 45 | Flickable { | 51 | Flickable { |
205 | 46 | id: checkoutFlickable | 52 | id: checkoutFlickable |
206 | 47 | anchors { | 53 | anchors { |
207 | @@ -261,13 +267,28 @@ | |||
208 | 261 | Keys.onReturnPressed: launchPurchase(); | 267 | Keys.onReturnPressed: launchPurchase(); |
209 | 262 | } | 268 | } |
210 | 263 | 269 | ||
211 | 270 | Label { | ||
212 | 271 | id: errorPasswordLabel | ||
213 | 272 | objectName: "errorPasswordLabel" | ||
214 | 273 | color: "red" | ||
215 | 274 | text: i18n.tr("Incorrect Password, please try again.") | ||
216 | 275 | wrapMode: Text.WordWrap | ||
217 | 276 | visible: selector.currentlyExpanded ? false : pageCheckout._errorVisible | ||
218 | 277 | anchors { | ||
219 | 278 | left: parent.left | ||
220 | 279 | right: parent.right | ||
221 | 280 | top: passwordField.bottom | ||
222 | 281 | margins: units.gu(1) | ||
223 | 282 | } | ||
224 | 283 | } | ||
225 | 284 | |||
226 | 264 | Rectangle { | 285 | Rectangle { |
227 | 265 | id: separator | 286 | id: separator |
228 | 266 | color: "#dedede" | 287 | color: "#dedede" |
229 | 267 | anchors { | 288 | anchors { |
230 | 268 | left: parent.left | 289 | left: parent.left |
231 | 269 | right: parent.right | 290 | right: parent.right |
233 | 270 | top: selector.currentlyExpanded ? manageCardLabel.bottom : passwordField.bottom | 291 | top: selector.currentlyExpanded ? manageCardLabel.bottom : errorPasswordLabel.bottom |
234 | 271 | topMargin: units.gu(2) | 292 | topMargin: units.gu(2) |
235 | 272 | } | 293 | } |
236 | 273 | height: 2 | 294 | height: 2 |
237 | 274 | 295 | ||
238 | === modified file 'app/ui/DirectPurchase.qml' | |||
239 | --- app/ui/DirectPurchase.qml 2014-06-25 20:58:29 +0000 | |||
240 | +++ app/ui/DirectPurchase.qml 2014-07-03 11:28:29 +0000 | |||
241 | @@ -27,10 +27,15 @@ | |||
242 | 27 | property alias account: accountView.model | 27 | property alias account: accountView.model |
243 | 28 | 28 | ||
244 | 29 | function launchPurchase() { | 29 | function launchPurchase() { |
245 | 30 | errorPasswordLabel.visible = false; | ||
246 | 30 | var email = accountView.currentItem.text; | 31 | var email = accountView.currentItem.text; |
247 | 31 | pageDirectPayment.buy(email, passwordField.text); | 32 | pageDirectPayment.buy(email, passwordField.text); |
248 | 32 | } | 33 | } |
249 | 33 | 34 | ||
250 | 35 | function showWrongPassword() { | ||
251 | 36 | errorPasswordLabel.visible = true; | ||
252 | 37 | } | ||
253 | 38 | |||
254 | 34 | Column { | 39 | Column { |
255 | 35 | spacing: units.gu(2) | 40 | spacing: units.gu(2) |
256 | 36 | anchors.fill: parent | 41 | anchors.fill: parent |
257 | @@ -96,6 +101,19 @@ | |||
258 | 96 | } | 101 | } |
259 | 97 | 102 | ||
260 | 98 | Label { | 103 | Label { |
261 | 104 | id: errorPasswordLabel | ||
262 | 105 | objectName: "errorPasswordLabel" | ||
263 | 106 | color: "red" | ||
264 | 107 | text: i18n.tr("Incorrect Password, please try again.") | ||
265 | 108 | wrapMode: Text.WordWrap | ||
266 | 109 | visible: false | ||
267 | 110 | anchors { | ||
268 | 111 | left: parent.left | ||
269 | 112 | right: parent.right | ||
270 | 113 | } | ||
271 | 114 | } | ||
272 | 115 | |||
273 | 116 | Label { | ||
274 | 99 | id: paymentTypeLabel | 117 | id: paymentTypeLabel |
275 | 100 | objectName: "paymentTypeLabel" | 118 | objectName: "paymentTypeLabel" |
276 | 101 | textFormat: Text.RichText | 119 | textFormat: Text.RichText |
277 | @@ -106,6 +124,7 @@ | |||
278 | 106 | right: parent.right | 124 | right: parent.right |
279 | 107 | } | 125 | } |
280 | 108 | onLinkActivated: { | 126 | onLinkActivated: { |
281 | 127 | errorPasswordLabel.visible = false; | ||
282 | 109 | pageDirectPayment.showPaymentTypes(); | 128 | pageDirectPayment.showPaymentTypes(); |
283 | 110 | } | 129 | } |
284 | 111 | } | 130 | } |
285 | 112 | 131 | ||
286 | === modified file 'app/ui/UbuntuPurchaseWebkit.qml' | |||
287 | --- app/ui/UbuntuPurchaseWebkit.qml 2014-06-23 18:20:45 +0000 | |||
288 | +++ app/ui/UbuntuPurchaseWebkit.qml 2014-07-03 11:28:29 +0000 | |||
289 | @@ -17,7 +17,7 @@ | |||
290 | 17 | import QtQuick 2.0 | 17 | import QtQuick 2.0 |
291 | 18 | import Ubuntu.Components 0.1 | 18 | import Ubuntu.Components 0.1 |
292 | 19 | import Ubuntu.Components.Popups 0.1 | 19 | import Ubuntu.Components.Popups 0.1 |
294 | 20 | import QtWebKit 3.0 | 20 | import com.canonical.Oxide 1.0 |
295 | 21 | 21 | ||
296 | 22 | 22 | ||
297 | 23 | Page { | 23 | Page { |
298 | @@ -26,7 +26,6 @@ | |||
299 | 26 | 26 | ||
300 | 27 | signal purchaseSucceeded() | 27 | signal purchaseSucceeded() |
301 | 28 | signal purchaseCanceled() | 28 | signal purchaseCanceled() |
302 | 29 | signal payTypeAdded() | ||
303 | 30 | signal loading(bool value) | 29 | signal loading(bool value) |
304 | 31 | 30 | ||
305 | 32 | property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0 | 31 | property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0 |
306 | @@ -75,9 +74,6 @@ | |||
307 | 75 | pageWebkit.closePurchase(); | 74 | pageWebkit.closePurchase(); |
308 | 76 | pageWebkit.purchaseCanceled(); | 75 | pageWebkit.purchaseCanceled(); |
309 | 77 | return; | 76 | return; |
310 | 78 | } else if(/^(purchase):\/\/payAdded/.test(request.url)) { | ||
311 | 79 | pageWebkit.payTypeAdded(); | ||
312 | 80 | return; | ||
313 | 81 | } | 77 | } |
314 | 82 | 78 | ||
315 | 83 | request.action = WebView.AcceptRequest; | 79 | request.action = WebView.AcceptRequest; |
316 | 84 | 80 | ||
317 | === modified file 'backend/modules/payui/network.cpp' | |||
318 | --- backend/modules/payui/network.cpp 2014-06-25 20:58:29 +0000 | |||
319 | +++ backend/modules/payui/network.cpp 2014-07-03 11:28:29 +0000 | |||
320 | @@ -34,6 +34,7 @@ | |||
321 | 34 | #define PAY_BASE_URL "https://sc.ubuntu.com/api/2.0/click/" | 34 | #define PAY_BASE_URL "https://sc.ubuntu.com/api/2.0/click/" |
322 | 35 | #define ACCOUNT_CREDS_URL "https://login.ubuntu.com/api/v2/tokens/oauth" | 35 | #define ACCOUNT_CREDS_URL "https://login.ubuntu.com/api/v2/tokens/oauth" |
323 | 36 | #define ADD_PAYMENT_URL "https://sc.ubuntu.com/api/2.0/click/paymentmethods/add/" | 36 | #define ADD_PAYMENT_URL "https://sc.ubuntu.com/api/2.0/click/paymentmethods/add/" |
324 | 37 | //<matiasb> gatox: this is the url, in staging: https://sc.staging.ubuntu.com/click/payment-method/add/ | ||
325 | 37 | 38 | ||
326 | 38 | #define PREFERED_PAYMENT_TYPE "0" | 39 | #define PREFERED_PAYMENT_TYPE "0" |
327 | 39 | #define PAYMENT_TYPES "1" | 40 | #define PAYMENT_TYPES "1" |
328 | @@ -159,11 +160,14 @@ | |||
329 | 159 | QString state = object.value("state").toString(); | 160 | QString state = object.value("state").toString(); |
330 | 160 | 161 | ||
331 | 161 | if (state == BUY_COMPLETE) { | 162 | if (state == BUY_COMPLETE) { |
332 | 163 | qDebug() << "BUY STATE: complete"; | ||
333 | 162 | Q_EMIT buyItemSucceeded(); | 164 | Q_EMIT buyItemSucceeded(); |
334 | 163 | } else if (state == BUY_IN_PROGRESS) { | 165 | } else if (state == BUY_IN_PROGRESS) { |
335 | 166 | qDebug() << "BUY STATE: in progress"; | ||
336 | 164 | QString redirect_to = object.value("redirect_to").toString(); | 167 | QString redirect_to = object.value("redirect_to").toString(); |
337 | 165 | Q_EMIT buyInteractionRequired(redirect_to); | 168 | Q_EMIT buyInteractionRequired(redirect_to); |
338 | 166 | } else { | 169 | } else { |
339 | 170 | qDebug() << "BUY STATE: failed"; | ||
340 | 167 | Q_EMIT buyItemFailed(); | 171 | Q_EMIT buyItemFailed(); |
341 | 168 | } | 172 | } |
342 | 169 | } else if (state->operation.contains(ITEM_INFO) && document.isObject()) { | 173 | } else if (state->operation.contains(ITEM_INFO) && document.isObject()) { |
343 | @@ -190,6 +194,8 @@ | |||
344 | 190 | Q_EMIT error(message); | 194 | Q_EMIT error(message); |
345 | 191 | } | 195 | } |
346 | 192 | 196 | ||
347 | 197 | } else if (httpStatus == 401 || httpStatus == 403) { | ||
348 | 198 | Q_EMIT authenticationError(); | ||
349 | 193 | } else { | 199 | } else { |
350 | 194 | Q_EMIT error(QString::number(httpStatus)); | 200 | Q_EMIT error(QString::number(httpStatus)); |
351 | 195 | } | 201 | } |
352 | 196 | 202 | ||
353 | === modified file 'backend/modules/payui/network.h' | |||
354 | --- backend/modules/payui/network.h 2014-06-25 20:58:29 +0000 | |||
355 | +++ backend/modules/payui/network.h 2014-07-03 11:28:29 +0000 | |||
356 | @@ -70,6 +70,7 @@ | |||
357 | 70 | void buyItemFailed(); | 70 | void buyItemFailed(); |
358 | 71 | void buyInteractionRequired(QString url); | 71 | void buyInteractionRequired(QString url); |
359 | 72 | void error(QString message); | 72 | void error(QString message); |
360 | 73 | void authenticationError(); | ||
361 | 73 | void credentialsNotFound(); | 74 | void credentialsNotFound(); |
362 | 74 | void credentialsFound(); | 75 | void credentialsFound(); |
363 | 75 | void credentialsUpdated(); | 76 | void credentialsUpdated(); |
364 | 76 | 77 | ||
365 | === modified file 'backend/modules/payui/purchase.cpp' | |||
366 | --- backend/modules/payui/purchase.cpp 2014-06-23 18:20:45 +0000 | |||
367 | +++ backend/modules/payui/purchase.cpp 2014-07-03 11:28:29 +0000 | |||
368 | @@ -26,6 +26,8 @@ | |||
369 | 26 | this, &Purchase::buyInterationRequired); | 26 | this, &Purchase::buyInterationRequired); |
370 | 27 | QObject::connect(&m_network, &Network::error, | 27 | QObject::connect(&m_network, &Network::error, |
371 | 28 | this, &Purchase::error); | 28 | this, &Purchase::error); |
372 | 29 | QObject::connect(&m_network, &Network::authenticationError, | ||
373 | 30 | this, &Purchase::authenticationError); | ||
374 | 29 | QObject::connect(&m_network, &Network::credentialsNotFound, | 31 | QObject::connect(&m_network, &Network::credentialsNotFound, |
375 | 30 | this, &Purchase::credentialsNotFound); | 32 | this, &Purchase::credentialsNotFound); |
376 | 31 | QObject::connect(&m_network, &Network::credentialsFound, | 33 | QObject::connect(&m_network, &Network::credentialsFound, |
377 | @@ -55,13 +57,21 @@ | |||
378 | 55 | 57 | ||
379 | 56 | void Purchase::quitCancel() | 58 | void Purchase::quitCancel() |
380 | 57 | { | 59 | { |
381 | 60 | qDebug() << "Purchase Canceled: exit code 1"; | ||
382 | 58 | QCoreApplication::exit(1); | 61 | QCoreApplication::exit(1); |
383 | 59 | } | 62 | } |
384 | 60 | 63 | ||
385 | 64 | void Purchase::quitSuccess() | ||
386 | 65 | { | ||
387 | 66 | qDebug() << "Purchase Succeeded: exit code 0"; | ||
388 | 67 | QCoreApplication::exit(0); | ||
389 | 68 | } | ||
390 | 69 | |||
391 | 61 | void Purchase::checkCredentials() | 70 | void Purchase::checkCredentials() |
392 | 62 | { | 71 | { |
393 | 63 | if (m_appid.isEmpty() && m_itemid.isEmpty()) { | 72 | if (m_appid.isEmpty() && m_itemid.isEmpty()) { |
395 | 64 | QCoreApplication::exit(1); | 73 | qDebug() << "AppId or ItemId not provided"; |
396 | 74 | quitCancel(); | ||
397 | 65 | } else { | 75 | } else { |
398 | 66 | qDebug() << "Getting Item Details"; | 76 | qDebug() << "Getting Item Details"; |
399 | 67 | getItemDetails(m_appid, m_itemid); | 77 | getItemDetails(m_appid, m_itemid); |
400 | 68 | 78 | ||
401 | === modified file 'backend/modules/payui/purchase.h' | |||
402 | --- backend/modules/payui/purchase.h 2014-06-23 18:20:45 +0000 | |||
403 | +++ backend/modules/payui/purchase.h 2014-07-03 11:28:29 +0000 | |||
404 | @@ -21,6 +21,7 @@ | |||
405 | 21 | Q_INVOKABLE void checkCredentials(); | 21 | Q_INVOKABLE void checkCredentials(); |
406 | 22 | Q_INVOKABLE QString getAddPaymentUrl(); | 22 | Q_INVOKABLE QString getAddPaymentUrl(); |
407 | 23 | 23 | ||
408 | 24 | Q_INVOKABLE void quitSuccess(); | ||
409 | 24 | Q_INVOKABLE void quitCancel(); | 25 | Q_INVOKABLE void quitCancel(); |
410 | 25 | 26 | ||
411 | 26 | Q_SIGNALS: | 27 | Q_SIGNALS: |
412 | @@ -30,6 +31,7 @@ | |||
413 | 30 | void buyItemFailed(); | 31 | void buyItemFailed(); |
414 | 31 | void buyInterationRequired(QString url); | 32 | void buyInterationRequired(QString url); |
415 | 32 | void error(QString message); | 33 | void error(QString message); |
416 | 34 | void authenticationError(); | ||
417 | 33 | void credentialsNotFound(); | 35 | void credentialsNotFound(); |
418 | 34 | void credentialsFound(); | 36 | void credentialsFound(); |
419 | 35 | 37 | ||
420 | 36 | 38 | ||
421 | === modified file 'backend/tests/mock_click_server.py' | |||
422 | --- backend/tests/mock_click_server.py 2014-06-23 18:20:45 +0000 | |||
423 | +++ backend/tests/mock_click_server.py 2014-07-03 11:28:29 +0000 | |||
424 | @@ -114,6 +114,12 @@ | |||
425 | 114 | self.end_headers() | 114 | self.end_headers() |
426 | 115 | self.wfile.write(bytes(json.dumps(response), 'UTF-8')) | 115 | self.wfile.write(bytes(json.dumps(response), 'UTF-8')) |
427 | 116 | 116 | ||
428 | 117 | def response_auth_error(self): | ||
429 | 118 | self.send_response(401) | ||
430 | 119 | self.send_header("Content-type", "application/json") | ||
431 | 120 | self.end_headers() | ||
432 | 121 | self.wfile.write(bytes(json.dumps(dict()), 'UTF-8')) | ||
433 | 122 | |||
434 | 117 | def do_POST(self): | 123 | def do_POST(self): |
435 | 118 | """Respond to a POST request.""" | 124 | """Respond to a POST request.""" |
436 | 119 | #content = self.rfile.read(int(self.headers.get('content-length'))) | 125 | #content = self.rfile.read(int(self.headers.get('content-length'))) |
437 | @@ -135,6 +141,8 @@ | |||
438 | 135 | elif self.path.find("iteminfo/") != -1: | 141 | elif self.path.find("iteminfo/") != -1: |
439 | 136 | fail = self.path.find("/fail/") != -1 | 142 | fail = self.path.find("/fail/") != -1 |
440 | 137 | self.response_item_info(fail) | 143 | self.response_item_info(fail) |
441 | 144 | elif self.path.find("/authError/") != -1: | ||
442 | 145 | self.response_auth_error() | ||
443 | 138 | elif self.path.find("shutdown") != -1: | 146 | elif self.path.find("shutdown") != -1: |
444 | 139 | global KEEP_ALIVE | 147 | global KEEP_ALIVE |
445 | 140 | KEEP_ALIVE = False | 148 | KEEP_ALIVE = False |
446 | 141 | 149 | ||
447 | === modified file 'backend/tests/test_network.cpp' | |||
448 | --- backend/tests/test_network.cpp 2014-06-25 20:58:29 +0000 | |||
449 | +++ backend/tests/test_network.cpp 2014-07-03 11:28:29 +0000 | |||
450 | @@ -40,6 +40,7 @@ | |||
451 | 40 | 40 | ||
452 | 41 | private slots: | 41 | private slots: |
453 | 42 | void initTestCase(); | 42 | void initTestCase(); |
454 | 43 | void testNetworkAuthenticationError(); | ||
455 | 43 | void testNetworkGetPaymentTypes(); | 44 | void testNetworkGetPaymentTypes(); |
456 | 44 | void testNetworkGetPaymentTypesFail(); | 45 | void testNetworkGetPaymentTypesFail(); |
457 | 45 | void testNetworkBuyItem(); | 46 | void testNetworkBuyItem(); |
458 | @@ -62,7 +63,7 @@ | |||
459 | 62 | void TestNetwork::initTestCase() | 63 | void TestNetwork::initTestCase() |
460 | 63 | { | 64 | { |
461 | 64 | qDebug() << "Starting Server"; | 65 | qDebug() << "Starting Server"; |
463 | 65 | // network.setCredentials(Token("token_key", "token_secret", "consumer_key", "consumer_secret")); | 66 | network.setCredentials(Token("token_key", "token_secret", "consumer_key", "consumer_secret")); |
464 | 66 | process = new QProcess(this); | 67 | process = new QProcess(this); |
465 | 67 | QSignalSpy spy(process, SIGNAL(started())); | 68 | QSignalSpy spy(process, SIGNAL(started())); |
466 | 68 | process->setWorkingDirectory(QDir::currentPath() + "/backend/tests/"); | 69 | process->setWorkingDirectory(QDir::currentPath() + "/backend/tests/"); |
467 | @@ -80,6 +81,15 @@ | |||
468 | 80 | QTRY_COMPARE(spy2.count(), 1); | 81 | QTRY_COMPARE(spy2.count(), 1); |
469 | 81 | } | 82 | } |
470 | 82 | 83 | ||
471 | 84 | void TestNetwork::testNetworkAuthenticationError() | ||
472 | 85 | { | ||
473 | 86 | setenv("ACCOUNT_CREDS_URL", "http://localhost:8000/authError/", 1); | ||
474 | 87 | setenv("PAY_BASE_URL", "http://localhost:8000/", 1); | ||
475 | 88 | QSignalSpy spy(&network, SIGNAL(authenticationError())); | ||
476 | 89 | network.buyItem("email", "password", "appid", "itemid", "paymentid", "backendid"); | ||
477 | 90 | QTRY_COMPARE(spy.count(), 1); | ||
478 | 91 | } | ||
479 | 92 | |||
480 | 83 | void TestNetwork::testNetworkGetPaymentTypes() | 93 | void TestNetwork::testNetworkGetPaymentTypes() |
481 | 84 | { | 94 | { |
482 | 85 | setenv("PAY_BASE_URL", "http://localhost:8000/", 1); | 95 | setenv("PAY_BASE_URL", "http://localhost:8000/", 1); |
483 | 86 | 96 | ||
484 | === modified file 'manifest.json' | |||
485 | --- manifest.json 2014-06-25 20:58:29 +0000 | |||
486 | +++ manifest.json 2014-07-03 11:28:29 +0000 | |||
487 | @@ -10,6 +10,6 @@ | |||
488 | 10 | "desktop": "payui.desktop" | 10 | "desktop": "payui.desktop" |
489 | 11 | } | 11 | } |
490 | 12 | }, | 12 | }, |
492 | 13 | "version": "0.2", | 13 | "version": "0.2.5", |
493 | 14 | "maintainer": "Sarmentero Diego <diego.sarmentero@canonical.com>" | 14 | "maintainer": "Sarmentero Diego <diego.sarmentero@canonical.com>" |
494 | 15 | } | 15 | } |
495 | 16 | \ No newline at end of file | 16 | \ No newline at end of file |
PASSED: Continuous integration, rev:6 jenkins. qa.ubuntu. com/job/ pay-ui- ci/19/ jenkins. qa.ubuntu. com/job/ generic- click-builder- utopic- armhf/203 jenkins. qa.ubuntu. com/job/ pay-ui- utopic- amd64-ci/ 16 jenkins. qa.ubuntu. com/job/ pay-ui- utopic- armhf-ci/ 16 jenkins. qa.ubuntu. com/job/ pay-ui- utopic- armhf-ci/ 16/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ pay-ui- utopic- i386-ci/ 16
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/pay- ui-ci/19/ rebuild
http://