-
Notifications
You must be signed in to change notification settings - Fork 153
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
chore: fix remaining shipping2 tests, complete initial refactor #13324
Conversation
fb61cce
to
17ac742
Compare
const handleSelectSavedAddress = async ( | ||
address: ShippingAddressFormValues | ||
) => { | ||
await setValues({ |
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 had to upgrade the formik version to give this the correct Promise return type (so that submitForm()
will hopefully work as expected)
src/Apps/Order/Routes/Shipping2/Components/FulfillmentDetailsForm.tsx
Outdated
Show resolved
Hide resolved
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.
Once tests are green, LGTM 👍
(And congrats on wrapping this all up 🎉)
e510542
to
cc9bd83
Compare
@@ -36,12 +36,21 @@ export const useSaveSelectedShippingQuote = ( | |||
try { | |||
shippingContext.actions.setIsPerformingOperation(true) | |||
|
|||
if ( | |||
shippingContext.state.fulfillmentDetailsCtx?.values.meta.mode === |
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.
todo: can this be stored/pulled directly from shippingContext.state
and not used in the form ctx?
I'll look into this but don't think it needs to block this PR.
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'm going to leave this for now because it also includes the pickup
mode, which isn't controlled from outside the component.
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.
update: I went ahead and did it. cleaner and also caught an invisible bug.
selectedSavedAddressId, | ||
shippingContext.orderData.availableShippingCountries | ||
)?.internalID | ||
const addressList = compact<SavedAddressType>( |
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.
Todo: Added addressList to shippingContext because it was used in hooks, and painful to thread in. But maybe this isn't necessary - a helper to compact an address list from anywhere could accomplish the same thing... Alternately it could be used here too instead of using local data from props.
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.
Comments on approach and major changes.
const updateDefaultAddress = useUpdateUserDefaultAddress() | ||
const shippingContext = useShippingContext() | ||
|
||
const handleNewUserAddressUpdates = async ( |
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 file is key to the changes because the hook controls all updates to user addresses. It includes
handleNewUserAddressUpdates
: deals with creating/updating/deleting a user's address when it is their first saved address (address form is still present, and they may edit it or even uncheck the box before saving shipping quotes)executeUserAddressAction
: Takes an action type (create/edit/delete) and performs that action, as well as setting as default if applicable. Used by the first method above.
Following this change all flows perform actions in the same order, Performing any user address updates before submitting fulfillment details/shipping quotes to exchange.
: null | ||
|
||
useEffect(() => { | ||
if ( | ||
bestArtsyShippingQuote && | ||
bestArtsyShippingQuote !== | ||
shippingContext.orderData.selectedShippingQuoteId | ||
shippingContext.orderData.selectedShippingQuoteID |
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.
A lot of diff in this PR is me making _ID
capitalization consistent. I chose the format used for internalID
"new_address" | ||
) { | ||
await handleNewUserAddressUpdates( | ||
shippingContext.state.fulfillmentDetailsCtx.values |
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.
An effect of letting a user edit values in 2 steps at once - if they change the address, the shipping quotes will disappear and they will be back on the fulfillment details step. But if they check/uncheck the box we just need to save/delete the address - hence this line, which for consistency now happens before saving the shipping quote.
Another way to do this could be to have the save/unsave mutation triggered from inside fulfillment details immediately upon clicking the box. Might be a good follow-up.
"Order/Routes/Shipping/Hooks/useHandleUserAddressUpdates.tsx" | ||
) | ||
|
||
export const useHandleUserAddressUpdates = () => { |
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.
moved to useUserAddressUpdates
* Go back to fulfillment details stage if the user edits the address or | ||
* deletes a saved address. | ||
*/ | ||
export const useBackToFullfillmentDetails = (me: Shipping2_me$data) => { |
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.
Moved this logic into a wrapper around specific handleChange
callbacks that should trigger the change. It's cleaner, less code and easier to trace.
onChange={trackAutoCompleteEdits("postalCode", handleChange)} | ||
onChange={withBackToFulfillmentDetails( | ||
trackAutoCompleteEdits("postalCode", handleChange) | ||
)} |
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.
useBackToFulfillmentDetails
hook behavior now wraps specific fields we want to track.
}, | ||
}) | ||
|
||
await formikContext.submitForm() |
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.
After saving a user's address, the form receives it in this callback, sets all the values (because it is in saved address mode the inputs are not visible) and submits the form. FulfillmentDetails controlls submitting the values to exchange only after SavedAddresses2 performs the user address updates.
export const GENERIC_FAIL_MESSAGE = | ||
"Sorry, there has been an issue saving your address. Please try again." | ||
|
||
const validationSchema = Yup.object().shape(ADDRESS_VALIDATION_SHAPE) | ||
const handleGravityErrors = ( | ||
errors: ReadonlyArray<{ message: string }>, |
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.
Gravity mutation helpers in useUserAddressUpdates
now always return a type something like {data: T} | {errors: [{message?: string}]} | null
(null if no action was performed). This lets us handle the errors a bit more consistently.
title="Full name" | ||
placeholder="Full name" | ||
id="name" | ||
name="attributes.name" |
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 copied these fields in so i could give them the attributes
key nesting. On reflection, I'm not sure if this was necessary or was part of an earlier attempt to get mutation-calling consistent.
<Form data-testid="AddressModal"> | ||
{formikContext.status && ( | ||
<Banner my={2} data-testid="form-banner-error" variant="error"> | ||
{formikContext.status} |
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.
using Formik's status
for this now.
* TODO: This could be accomplished with useImperativeHandle(ref, formikContext) | ||
*/ | ||
shippingContext.actions.setFormHelpers(formikContext) | ||
shippingContext.actions.setFulfillmentDetailsCtx(formikContext) |
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.
We should be more descriptive in the name of this function, just so we can see that its a formik context versus some other type of context:
shippingContext.actions.setFulfillmentDetailsFormikContext(formikContext)
} | ||
const addAddressButton = screen.getByText("Add a new address") | ||
await userEvent.click(addAddressButton) | ||
logTime("clicked button") |
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.
Might want to remove these loggers before merge (though i can see how they might be helpful for future devs, too)
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.
Yeah, maybe I can just link to this comment and make a ticket for it. Basically what I found was that the fillAddressForm
helper takes a long time, not so much things related to relay.
type: string | ||
} | ||
|
||
export const useHandleSaveFulfillmentDetails = () => { |
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.
Maybe just useSaveFulfillmentDetails
, since the handleSaveFulfillmentDetails
return value is just below? No need to double up
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.
yeah, why did I do this ... 🤔 ...
useSaveFulfillmentDetails
is theuseMutation
hook for just that operation- This hook includes prepping the values for the different mutation inputs (pickup, ship, artsy shipping) as well as the error handling
I'll try to think about better naming.
@@ -30,7 +30,7 @@ export function useFeatureFlag(featureName: string): boolean | null { | |||
|
|||
if (flagEnabled === undefined) { | |||
warnInDevelopment( | |||
"[Force] Warning: cannot find flagName in featureFlags: ", | |||
`[Force] Warning: cannot find ${featureName} in featureFlags: `, |
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.
👌
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.
Beautiful @erikdstock 💯
d851497
to
4fd4675
Compare
cleanup: remove console logs
b8f6f08
to
e429d41
Compare
The type of this PR is: chore
It completes EMI-1526 and relates to EMI-1520. After this PR all existing legacy tests will have been implemented, opening the door to more refactoring. All skipped tests have been unskipped (there will be failures while in draft), but TODOs remain in the test file.
Summary of changes
The diff is quite large because of fixing these final specs revealed some bigger changes that were necessary.
old notes
Functionality
Because the fulfillment details steps has two separate form layouts (saved addresses with a modal, or no saved addresses with a form on the page itself) there are multiple different flows to account for:
a)
is new functionality designed to avoid a bug mentioned in EMI-1520 and below and it does this by comparing address fields.Edge cases and possible bugs
So far in this draft PR I've covered most of these cases, but there may be more, especially with the edge cases noted in EMI-1520.
=>
The originally-saved address may be clobbered by the auto-saving feature, since their original address won't be in the saved address list.