-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use query parameters when loading checkout page #283
Conversation
a7a8cd9
to
701d92d
Compare
Codecov Report
@@ Coverage Diff @@
## master #283 +/- ##
==========================================
+ Coverage 94.12% 94.21% +0.08%
==========================================
Files 160 160
Lines 5400 5458 +58
Branches 312 312
==========================================
+ Hits 5083 5142 +59
+ Misses 261 260 -1
Partials 56 56
Continue to review full report at Codecov.
|
701d92d
to
5e38da3
Compare
5e38da3
to
55facf1
Compare
55facf1
to
0a7f7d9
Compare
0a7f7d9
to
bee77a7
Compare
bee77a7
to
316b187
Compare
316b187
to
cfeb6ce
Compare
cfeb6ce
to
e7206a9
Compare
: null | ||
) | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One comment off the top: I would rather have multiple test cases with some repeated code than a parametrized test case with this many lines and this many logical paths to reason about
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...actually I changed my mind. I think this can be cleaned up in a way that makes the parametrization a little more readable and maintainable
describe("mount", () => {
const productError = "product error",
couponError = "coupon error",
couponCode = "codeforcoupon",
productId = 12345
let couponPayload,productPayload
beforeEach(() => {
couponPayload = {
body: {coupons: [{code: couponCode}]},
credentials: undefined,
headers: {
"X-CSRFTOKEN": null
}
}
productPayload = {
body: {items: [{id: productId}]},
credentials: undefined,
headers: {
"X-CSRFTOKEN": null
}
}
})
//
;[
[true, false, couponError],
[true, true, null],
[false, false, productError],
[false, true, productError]
].forEach(
([hasValidProductId, hasValidCoupon, expError]) => {
it(`...`, async () => {
if (!hasValidProductId) {
helper.handleRequestStub
//...
.returns({
//...
body: {
errors: productError
}
})
}
if (!hasValidCoupon) {
helper.handleRequestStub
//...
.returns({
//...
body: {
errors: couponError
}
})
}
//...
assert.equal(
helper.handleRequestStub.calledWith(
"/api/basket/",
"PATCH",
couponPayload
),
hasValidProductId
)
assert.equal(
inner.state().errors,
expError
)
})
}
)
})
|
||
const couponCode = params.code | ||
if (couponCode) { | ||
await this.updateBasket({ coupons: [{ code: couponCode }] }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this isn't already possible, can this query/endpoint be rewritten to accept items
and coupons
in the same call? Executing 2 requests seems unnecessary here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little tricky because the behavior we want is to update items
then update coupons
. If the coupons
update fails the items
update should still succeed. If both were sent as the same PATCH request and the coupons
had a validation error but the items
succeeded, I think the proper thing is to not make any changes and return a 400 error with an error message in the payload. What do you think?
static/js/lib/ecommerce.js
Outdated
@@ -57,6 +58,24 @@ const formatDateForRun = (dateString: ?string) => | |||
export const formatRunTitle = (run: CourseRun) => | |||
`${formatDateForRun(run.start_date)} - ${formatDateForRun(run.end_date)}` | |||
|
|||
export const formatErrors = (errors: string | Object) => { | |||
if (!errors) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Seems like this logic will be needed outside of ecommerce. Might be better to define it in
static/js/lib/form.js
,static/js/lib/api.js
, etc. - A return type should be added to this function
- This should have some tests, right? Especially since (1) we may end up enforcing some standards around how errors are returned in back end responses, and (2) it's likely that we'll want to make changes to the JSX that this produces
- If this function can only accept
string
andObject
types, I don't think!errors
can ever evaluate to true. We might want to useemptyOrNil
iferrors
can be an empty object, empty string, ornull
/undefined
} | ||
) | ||
// wait for componentDidMount to resolve | ||
await wait(15) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there's no nice way to avoid this, but I'm wondering about option 2 in this GH post: enzymejs/enzyme#1587 (comment). If that seems to work, I think I'd prefer it over the wait
Ok, I think that's everything |
|
||
import queries from "../../lib/queries" | ||
import { | ||
calculateDiscount, | ||
calculatePrice, | ||
formatPrice, | ||
formatRunTitle | ||
formatRunTitle, | ||
formatErrors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function doesn't exist in lib/ecommerce
so this is breaking webpack
"PATCH", | ||
couponPayload | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer this if/else
be changed to a single assert
statement (assert.equal(helper.handleRequestStub.calledWith(...), hasValidProductId)
) but you can take or leave that
18f5912
to
0986ed1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 👍
Pre-Flight checklist
What are the relevant tickets?
Fixes #121
What's this PR do?
Uses query parameters to populate the basket on checkout page load. This will allow links from the catalog pages to the checkout page.
How should this be manually tested?
Go to
/checkout/?product_id=123456
where123456
is a validProductVersion
id. You should see that page loaded. If you go to?product_id=123456&code=xyz
for a valid coupon code, it should automatically apply the discount and show it on the checkout page.If you have no query parameters, it should show you whatever your basket looked like previously.
If you have an invalid product id, the page should load with whatever the old basket content was and an error message should be displayed at the bottom of the screen. This is a rare case so the error message won't be more prominent than that.
If you have an invalid coupon code, the page should try again to patch the basket with the given product id from the query parameter and an error message should be displayed at the bottom of the screen, near the coupon code textbox.