Closed Bug 1383300 Opened 8 years ago Closed 7 years ago

Show origin and total roughly similar to the UX specs

Categories

(Firefox :: WebPayments UI, enhancement, P1)

enhancement

Tracking

()

RESOLVED FIXED
Firefox 58
Tracking Status
firefox57 --- wontfix
firefox58 --- fixed

People

(Reporter: jonathanGB, Assigned: jonathanGB)

References

Details

Attachments

(4 files, 1 obsolete file)

In the dialog, we want: 1- to show the origin of the PaymentRequest at the top (like `foo.com`) 2- near the bottom, show the total amount of the request with its label
Priority: -- → P1
Attachment #8889639 - Flags: review?(MattN+bmo) → review+
Attachment #8889639 - Attachment is obsolete: true
Comment on attachment 8911068 [details] Bug 1383300 - Show payment request total and origin in the dialog. https://reviewboard.mozilla.org/r/182534/#review194994
Attachment #8911068 - Flags: review?(MattN+bmo) → review+
Comment on attachment 8918970 [details] Bug 1383300 - Test total and domain in the payment request dialog https://reviewboard.mozilla.org/r/189862/#review195242 Couple of nits, but looks good. ::: toolkit/components/payments/test/browser/browser_host_name.js:4 (Diff revision 1) > +"use strict"; > + > +async function withBasicRequestDialogForOrigin(origin, dialogTaskFn) { > + let args = { nit: s/let/const ::: toolkit/components/payments/test/browser/browser_total.js:4 (Diff revision 1) > +"use strict"; > + > +/* eslint-disable mozilla/no-cpows-in-tests */ > +add_task(async function test_total() { nit: bit easier to read: ```JS add_task(async function test_total() { const testTest = ({ methodData, details }) => { is( content.document.querySelector("#total > .value").textContent, details.total.amount.value, "Check total value" ); is( content.document.querySelector("#total > .currency").textContent, details.total.amount.currency, "Check currency" ); }; const options = { methodData: [PTU.MethodData.basicCard], details: PTU.Details.total60USD, }; await spawnInDialogForMerchantTask(PTU.ContentTasks.createRequest, theTest, options); }); ```
Attachment #8918970 - Flags: review?(mcaceres) → review+
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review195244 There might be a couple of potential issues around promises with this one (unless I've misunderstood how the underlying implementation works). Made a couple of suggestions. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:14 (Diff revision 3) > - * Common content tasks functions to be used with ContentTask.spawn. > + * Common content tasks functions to be used with ContentTask.spawn. > - */ > + */ > -let ContentTasks = { > + ContentTasks: { > + /* eslint-env mozilla/frame-script */ > + createRequest: async ({methodData, details, options}) => { > + let rq = new content.PaymentRequest(methodData, details, options); nit: s/let/const ::: toolkit/components/payments/test/PaymentTestUtils.jsm:15 (Diff revision 3) > - */ > + */ > -let ContentTasks = { > + ContentTasks: { > + /* eslint-env mozilla/frame-script */ > + createRequest: async ({methodData, details, options}) => { > + let rq = new content.PaymentRequest(methodData, details, options); > + content.rq = rq; // assign it so we can retrieve it later Will this be racy? if you call createRequest() multiple, they will trash eachother. Maybe swicth this to a regular function also. Nothing in this function is actually asycn. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:18 (Diff revision 3) > + createRequest: async ({methodData, details, options}) => { > + let rq = new content.PaymentRequest(methodData, details, options); > + content.rq = rq; // assign it so we can retrieve it later > + }, > + > - createAndShowRequest: async ({methodData, details, options}) => { > + createAndShowRequest: async ({methodData, details, options}) => { Should include JSDoc style documetation here, to match other methods. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:19 (Diff revision 3) > + let rq = new content.PaymentRequest(methodData, details, options); > + content.rq = rq; // assign it so we can retrieve it later > + }, > + > - createAndShowRequest: async ({methodData, details, options}) => { > + createAndShowRequest: async ({methodData, details, options}) => { > - let rq = new content.PaymentRequest(methodData, details, options); > + let rq = new content.PaymentRequest(methodData, details, options); here you should probably: ```JS const rq = this.createRequest(...); ``` ::: toolkit/components/payments/test/PaymentTestUtils.jsm:21 (Diff revision 3) > + }, > + > - createAndShowRequest: async ({methodData, details, options}) => { > + createAndShowRequest: async ({methodData, details, options}) => { > - let rq = new content.PaymentRequest(methodData, details, options); > + let rq = new content.PaymentRequest(methodData, details, options); > - content.rq = rq; // assign it so we can retrieve it later > + content.rq = rq; // assign it so we can retrieve it later > - rq.show(); > + rq.show(); This needs to either return the .show() promise here or `await` it, or we are going to have a a bad time :) ::: toolkit/components/payments/test/PaymentTestUtils.jsm:49 (Diff revision 3) > + }, > > -add_task(async function setup_head() { > - await SpecialPowers.pushPrefEnv({set: [[PREF_PAYMENT_ENABLED, true]]}); > -}); > + /** > + * Common PaymentDetailsInit for testing > + */ > + Details: { I wonder if we should just have a factory for these - otherwise, we are going to keep having to add new props every time we want to change values: ```JS Details.makeTotal(currency = "USD", value = "1.0", label: "Total Due"){ return { currency, value, label }; }; ``` We can also get fancy later and get it to spit out randomized values (and invalid ones). ::: toolkit/components/payments/test/browser/head.js:76 (Diff revision 3) > > function spawnPaymentDialogTask(paymentDialogFrame, taskFn, args = null) { > return ContentTask.spawn(paymentDialogFrame.frameLoader, args, taskFn); > } > > -/** > +async function withMerchantTab({browser = gBrowser, url = BLANK_PAGE_URL} = { nit: Bit cleaner. ```JS const defaultOptions = Object.freeze({ browser: gBrowser, url: BLANK_PAGE_URL, }); async function withMerchantTab(options, taskFn) { const { browser: gBrowser, url } = { ...defaultOptions, ...options }; await BrowserTestUtils.withNewTab({ gBrowser, url }, taskFn); } ``` ::: toolkit/components/payments/test/browser/head.js:105 (Diff revision 3) > + url: `chrome://payments/content/paymentDialog.xhtml?requestId=${requestId}`, > }, > -}; > + dialogTabTask); > +} > + > +function spawnTaskInNewDialog(requestId, contentTaskFn, args = null) { Do we really need this function? It seems like a lot of indirection to just call `withNewDialogFrame()` ::: toolkit/components/payments/test/browser/head.js:111 (Diff revision 3) > + return withNewDialogFrame(requestId, async function spawnTaskInNewDialog_tabTask(reqFrame) { > + await spawnPaymentDialogTask(reqFrame, contentTaskFn, args); > + }); > +} > + > +async function spawnInDialogForMerchantTask(merchantTaskFn, dialogTaskFn, taskArgs, { nit: bit cleaner: ```JS const exmpleOrigin = "https://example.com"; async function spawnInDialogForMerchantTask( merchantTaskFn, dialogTaskFn, taskArgs, origin = exmpleOrigin ) { const url = origin + BLANK_PAGE_PATH; await withMerchantTab({ url }, async merchBrowser => { await ContentTask.spawn( merchBrowser, taskArgs, PTU.ContentTasks.createRequest ); const requests = getPaymentRequests(); is(requests.length, 1, "Should have one payment request"); let request = requests[0]; ok(Boolean(request.requestId), "Got a payment request with an ID"); await spawnTaskInNewDialog(request.requestId, dialogTaskFn, taskArgs); }); } ``` ::: toolkit/components/payments/test/browser/head.js:131 (Diff revision 3) > + await spawnTaskInNewDialog(request.requestId, dialogTaskFn, taskArgs); > + }); > +} > > add_task(async function setup_head() { > - await SpecialPowers.pushPrefEnv({set: [[PREF_PAYMENT_ENABLED, true]]}); > + SimpleTest.registerCleanupFunction(function cleanup() { Nit - you can just: ```JS SimpleTest.registerCleanupFunction( paymentSrv.cleanup.bind(paymentSrv) ); ```
Attachment #8918357 - Flags: review?(mcaceres) → review-
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review195244 > nit: bit cleaner: > > ```JS > const exmpleOrigin = "https://example.com"; > async function spawnInDialogForMerchantTask( > merchantTaskFn, > dialogTaskFn, > taskArgs, > origin = exmpleOrigin > ) { > const url = origin + BLANK_PAGE_PATH; > await withMerchantTab({ url }, async merchBrowser => { > await ContentTask.spawn( > merchBrowser, > taskArgs, > PTU.ContentTasks.createRequest > ); > const requests = getPaymentRequests(); > is(requests.length, 1, "Should have one payment request"); > let request = requests[0]; > ok(Boolean(request.requestId), "Got a payment request with an ID"); > await spawnTaskInNewDialog(request.requestId, dialogTaskFn, taskArgs); > }); > } > > ``` s/exmpleOrigin/exampleOrigin Spelling is hard!
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review195244 > Will this be racy? if you call createRequest() multiple, they will trash eachother. > > Maybe swicth this to a regular function also. Nothing in this function is actually asycn. Yeah, perhaps we should have an array of requests but until we know what we need I'd rather not change this. It should be easy to change since only browser_show_dialog.js relies on it. > here you should probably: > > ```JS > const rq = this.createRequest(...); > ``` The methods in `ContentTasks` are used with ContentTask.jsm and the method body is serialized as a string when sent to the content process so it wouldn't be able to resolve `this.createRequest`. We could instead move some of the content tasks to be methods defined in blank.html (renamed) to do what you want. > This needs to either return the .show() promise here or `await` it, or we are going to have a a bad time :) Since we need to test the contents of the dialog we need to run code before it's completed but awaiting/returning will block us from testing: https://dxr.mozilla.org/mozilla-central/rev/20d57b9c4183973af4af5e078dff2aec0b74f928/testing/mochitest/BrowserTestUtils/ContentTask.jsm#61-62 Test code will need to listen for new dialogs in the UI rather than use the DOM promise. > I wonder if we should just have a factory for these - otherwise, we are going to keep having to add new props every time we want to change values: > > ```JS > Details.makeTotal(currency = "USD", value = "1.0", label: "Total Due"){ > return { currency, value, label }; > }; > ``` > > We can also get fancy later and get it to spit out randomized values (and invalid ones). My thinking was that we would representive valid and invalid examples on this object so each test doesn't have to come up with their own values (which takes more typing and distracts from the test content). I'm not sure if you're saying we should have predefined details object but then also have a factory to make others? > nit: Bit cleaner. > > ```JS > const defaultOptions = Object.freeze({ > browser: gBrowser, > url: BLANK_PAGE_URL, > }); > async function withMerchantTab(options, taskFn) { > const { browser: gBrowser, url } = { ...defaultOptions, ...options }; > await BrowserTestUtils.withNewTab({ gBrowser, url }, taskFn); > } > > ``` So basically you don't like the es7 way of default destructuring args? I like that with the way I have it, the method signature explains how arguments are handled. > Do we really need this function? It seems like a lot of indirection to just call `withNewDialogFrame()` Well it will save two lines for every caller and I think concise test cases make then easier to review. > s/exmpleOrigin/exampleOrigin > > Spelling is hard! My thinking was that there will be other options that will want to be changed when the default origin is fine so that's why I used an object arg. > Nit - you can just: > > ```JS > SimpleTest.registerCleanupFunction( > paymentSrv.cleanup.bind(paymentSrv) > ); > ``` Yeah, you're right but I'm pretty sure we'll need more here in the future.
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review196172 couple of nits. Please check the potential race condition with `getPaymentRequest()` (could lead to intermitten test failure pain)... we might need to work out some kind of timeout or other means of rejecting there. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:23 (Diff revisions 3 - 4) > - MethodData: { > - basicCard: { > - supportedMethods: "basic-card", > - }, > - }, > + .getService().wrappedJSObject; > +const {PaymentTestUtils: PTU} = Cu.import("resource://testing-common/PaymentTestUtils.jsm", {}); > + > +function getPaymentRequests() { > + let requestsEnum = paymentSrv.enumerate(); > + let requests = []; nit: const ::: toolkit/components/payments/test/PaymentTestUtils.jsm:47 (Diff revisions 3 - 4) > - }, > - }, > - }, > -}; > + }, "payment dialog should be the most recent"); > + > + return win; > +} > + > +async function getPaymentFrame(widget) { nit, remove "async" - just return, and let the consumer auto-wrap it. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:51 (Diff revisions 3 - 4) > + > +async function getPaymentFrame(widget) { > + return widget.document.getElementById("paymentRequestFrame"); > +} > + > +async function waitForMessageFromWidget(messageType, widget = null) { nit: drop async here too. It's already returning a promise. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:61 (Diff revisions 3 - 4) > + return; > + } > + if (widget && widget != target) { > + return; > + } > + resolve(); This looks like it could get into a race condition. If the widget is null, shouldn't it throw? ::: toolkit/components/payments/test/PaymentTestUtils.jsm:76 (Diff revisions 3 - 4) > + > +function spawnPaymentDialogTask(paymentDialogFrame, taskFn, args = null) { > + return ContentTask.spawn(paymentDialogFrame.frameLoader, args, taskFn); > +} > + > +async function withMerchantTab({browser = gBrowser, url = BLANK_PAGE_URL} = { Nit: I'm still not a huge fan of these kinds of signatures, because they are hard to reason about. However, can def live with it. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:87 (Diff revisions 3 - 4) > + url, > + }, taskFn); > + > + paymentSrv.cleanup(); // Temporary measure until bug 1408234 is fixed. > + > + return new Promise(resolve => { nit: ```js await new Promise(...) ``` Otherwise you will send back te result of `SpecialPowers.exactGC` to the caller - which might be confusing. ::: toolkit/components/payments/test/PaymentTestUtils.jsm:102 (Diff revisions 3 - 4) > + > + return BrowserTestUtils.withNewTab({ > + gBrowser, > + url: `chrome://payments/content/paymentDialog.xhtml?requestId=${requestId}`, > + }, > + dialogTabTask); nit: whitespace ::: toolkit/components/payments/test/PaymentTestUtils.jsm:111 (Diff revisions 3 - 4) > + return withNewDialogFrame(requestId, async function spawnTaskInNewDialog_tabTask(reqFrame) { > + await spawnPaymentDialogTask(reqFrame, contentTaskFn, args); > + }); > +} > + > +async function spawnInDialogForMerchantTask(merchantTaskFn, dialogTaskFn, taskArgs, { Nit, as above: this function signature is really hard to read.
Attachment #8918357 - Flags: review?(mcaceres) → review+
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review196172 > Nit, as above: this function signature is really hard to read. (feel free to ignore, I'll get used get used to it :) )
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review195244 > My thinking was that we would representive valid and invalid examples on this object so each test doesn't have to come up with their own values (which takes more typing and distracts from the test content). > > I'm not sure if you're saying we should have predefined details object but then also have a factory to make others? I'm ok with either approach (having a factory, and having predifined objects). > So basically you don't like the es7 way of default destructuring args? I like that with the way I have it, the method signature explains how arguments are handled. Can definately live with it. Maybe just need to get used to it. > My thinking was that there will be other options that will want to be changed when the default origin is fine so that's why I used an object arg. I see. Thanks for clarifying.
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review196172 > nit: const In Fx front-end we normally only use constants with a more traditional meaning that they won't change e.g. with primitives and the Mozilla coding style says they should be UPPERCASE_WITH_SNAKES. I'm not sure I want to diverge this module from the rest. > nit, remove "async" - just return, and let the consumer auto-wrap it. I did this because I don't want consumers to rely on this being synchronous as it very likely won't be when we change to a new widget. > This looks like it could get into a race condition. > > If the widget is null, shouldn't it throw? I made widget an optional argument so that in the case where only one widget is open at a time (most tests) that we don't have to add complexity checking the right widget is used. > nit: whitespace It's aligned with the beginning of the first argument which is normal but I agree it looks weird so I moved the object to a temp var. > (feel free to ignore, I'll get used get used to it :) ) I'm not in love with the syntax that the es WG came up with but I also don't want to fight it since it's here to stay. :P
Pushed by mozilla@noorenberghe.ca: https://hg.mozilla.org/integration/autoland/rev/73115b197e08 Show payment request total and origin in the dialog. r=MattN https://hg.mozilla.org/integration/autoland/rev/4b4b4cad9bf5 Move common payment tasks, methods and details to PaymentTestUtils. r=marcosc https://hg.mozilla.org/integration/autoland/rev/59db547d0dab Test total and domain in the payment request dialog r=marcosc
We're sorry, Autoland could not rebase your commits for you automatically. Please manually rebase your commits and try again. hg error in cmd: hg rebase -s 9f842ee901f9 -d 59db547d0dab: rebasing 428735:9f842ee901f9 "Bug 1383300 - Show payment request total and origin in the dialog. r=MattN" note: rebase of 428735:9f842ee901f9 created no changes to commit rebasing 428736:254f7546ca4d "Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. r=marcosc" merging toolkit/components/payments/test/PaymentTestUtils.jsm merging toolkit/components/payments/test/browser/browser.ini warning: conflicts while merging toolkit/components/payments/test/PaymentTestUtils.jsm! (edit, then use 'hg resolve --mark') warning: conflicts while merging toolkit/components/payments/test/browser/browser.ini! (edit, then use 'hg resolve --mark') unresolved conflicts (see hg resolve, then hg rebase --continue)
Backed out for ESlint failure at toolkit/components/payments/test/PaymentTestUtils.jsm:26 and failing own browser_host_name.js: https://hg.mozilla.org/integration/autoland/rev/8e18b993db1ceb9f8e0b1c260a63bcfdff492f5b https://hg.mozilla.org/integration/autoland/rev/7704cf5707a9b4a0db0fd3d538b15a07e2f5a076 https://hg.mozilla.org/integration/autoland/rev/062dbecb38a63df8ce25cb90a79dfa5645a154cc Push with failures: https://treeherder.mozilla.org/#/jobs?repo=autoland&revision=59db547d0dab13e5a906669ba6b6fba9a4173889&filter-resultStatus=testfailed&filter-resultStatus=busted&filter-resultStatus=exception&filter-resultStatus=usercancel&filter-resultStatus=runnable&filter-resultStatus=retry Failure log eslint: https://treeherder.mozilla.org/logviewer.html#?job_id=138635071&repo=autoland > TEST-UNEXPECTED-ERROR | /builds/worker/checkouts/gecko/toolkit/components/payments/test/PaymentTestUtils.jsm:26:5 | Unexpected @returns tag; function has no return statement. (valid-jsdoc) Failure browser-chrome: https://treeherder.mozilla.org/logviewer.html#?job_id=138636379&repo=autoland /xul.css" line: 460}] 18:02:31 INFO - TEST-PASS | toolkit/components/payments/test/browser/browser_host_name.js | Should have one payment request - 18:02:31 INFO - TEST-PASS | toolkit/components/payments/test/browser/browser_host_name.js | Got a payment request with an ID - 18:02:31 INFO - Buffered messages finished 18:02:31 INFO - TEST-UNEXPECTED-FAIL | toolkit/components/payments/test/browser/browser_host_name.js | Uncaught exception - TypeError: content.document.querySelector(...) is null 18:02:31 INFO - Leaving test bound test_host
Flags: needinfo?(MattN+bmo)
Comment on attachment 8918357 [details] Bug 1383300 - Move common payment tasks, methods and details to PaymentTestUtils. https://reviewboard.mozilla.org/r/189152/#review201644 ::: toolkit/components/payments/test/browser/head.js:94 (Diff revision 7) > - content.document.getElementById("cancel").click(); > - }, > + let paymentRequestFrame = dialogBrowser.contentDocument.getElementById("paymentRequestFrame"); > + await taskFn(paymentRequestFrame); I believe the test failure was because even though we wait for the privileged dialog URL to load, the inner #paymentRequestFrame may not have loaded yet so the content task was spawned on it too early. Try push: https://treeherder.mozilla.org/#/jobs?repo=try&revision=c3c8bd35a9e2f572e45c56b7fda459ef6d6dfaad
Comment on attachment 8925183 [details] Bug 1383300 - withNewDialogFrame should wait for the inner frame load. https://reviewboard.mozilla.org/r/196424/#review201648
Attachment #8925183 - Flags: review?(MattN+bmo) → review+
Flags: needinfo?(MattN+bmo)
Pushed by mozilla@noorenberghe.ca: https://hg.mozilla.org/integration/autoland/rev/34fa5b4d4d59 Show payment request total and origin in the dialog. r=MattN https://hg.mozilla.org/integration/autoland/rev/71b84c813705 Move common payment tasks, methods and details to PaymentTestUtils. r=marcosc https://hg.mozilla.org/integration/autoland/rev/908e2e2a759b Test total and domain in the payment request dialog r=marcosc https://hg.mozilla.org/integration/autoland/rev/bc8f24ca5bb3 withNewDialogFrame should wait for the inner frame load. r=MattN
Pushed by archaeopteryx@coole-files.de: https://hg.mozilla.org/integration/autoland/rev/3879080f60c2 withNewDialogFrame should wait for the inner frame load: add semicolon. r=eslint-fix
Pushed by mozilla@noorenberghe.ca: https://hg.mozilla.org/integration/autoland/rev/77f59f25cec7 Show payment request total and origin in the dialog. r=MattN https://hg.mozilla.org/integration/autoland/rev/e15196c8d960 Move common payment tasks, methods and details to PaymentTestUtils. r=marcosc https://hg.mozilla.org/integration/autoland/rev/d2b74001fefc Test total and domain in the payment request dialog r=marcosc https://hg.mozilla.org/integration/autoland/rev/4f270f7da185 withNewDialogFrame should wait for the inner frame load. r=MattN
Product: Toolkit → Firefox
Target Milestone: mozilla58 → Firefox 58
Version: unspecified → Trunk
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: