-
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
feat(EMI-2196): Consolidated global AddressFormFields component + usage in Auction/Invoice apps #14898
base: main
Are you sure you want to change the base?
Conversation
- maybe move phone number into address object on address type since it is already redundantly in there?
#1017 Bundle Size — 9.54MiB (-0.07%).13be370(current) vs ffe4f84 main#484(baseline) Important Bundle introduced 1 and removed 4 duplicate packages – View changed duplicate packages Warning Bundle introduced 3 new packages: web-vitals, @sentry-internal/browser-utils, stylis – View changed packages Bundle metrics
|
Current #1017 |
Baseline #484 |
|
---|---|---|
Initial JS | 3.69MiB (-6.58% ) |
3.95MiB |
Initial CSS | 0B |
0B |
Cache Invalidation | 87.74% |
2.04% |
Chunks | 141 (-1.4% ) |
143 |
Assets | 145 (-0.68% ) |
146 |
Modules | 5690 (+0.94% ) |
5637 |
Duplicate Modules | 495 (+8.79% ) |
455 |
Duplicate Code | 5.87% (-0.17% ) |
5.88% |
Packages | 282 (-3.09% ) |
291 |
Duplicate Packages | 39 (-7.14% ) |
42 |
Bundle size by type 2 changes
1 regression
1 improvement
Current #1017 |
Baseline #484 |
|
---|---|---|
JS | 9.33MiB (+0.2% ) |
9.31MiB |
Other | 212.46KiB (-10.67% ) |
237.84KiB |
Bundle analysis report Branch erik.emi2196-invoice-address-for... Project dashboard
Generated by RelativeCI Documentation Report issue
@@ -10,7 +11,7 @@ export const AddressFormWithCreditCard: React.FC<React.PropsWithChildren<unknown | |||
setFieldError, | |||
errors, | |||
touched, | |||
} = useFormContext() | |||
} = useAuctionFormContext() |
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 changed because the name was coming up in searches in multiple places and caused me to confuse myself. Maybe not worth it though.
phoneNumber: string | ||
} | ||
|
||
export const AddressFormFields = <V extends FormikContextWithAddress>() => { |
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.
Type parameter here helps guarantee that the useFormikContext()
call below will be able to service our fields.
I'll re-open this when it's ready for merge. |
if (!values.address) { | ||
helpers.setStatus("SUBMISSION_FAILED") | ||
return | ||
} |
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 caused a bunch of test failures [fixed here] even though I don't think it would be an issue in real life due to form validations. I only did it to satisfy some ts complaints about using the !
so we could remove it.
Hmm, I see some more validation schemas that I might need to reconcile:
OTOH maybe this is ok as long as the validations work - but it would be nice to keep it all consistent and in one place. |
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.
PR tour.
export interface Address { | ||
name: string | ||
country: string | ||
postalCode: string | ||
addressLine1: string | ||
addressLine2: string | ||
city: string | ||
region: string | ||
phoneNumber?: 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.
PR Tour start: This file contains a non-formik address form layout which is only used on the checkout>payment route. I'm considering it deprecated so moved most utility types and constants to a nearby file.
interface FormikContextWithAddress { | ||
address: Address | ||
phoneNumber?: 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.
Most of the PR is here: I promoted the Apps/Auction/Components/Form/AddressForm.tsx
file to live in Components/Address/AddressFormFields.tsx
. It is now used by both the auction and invoice apps for their credit card forms, and is named with Fields
because it is only the fields.
- This file also exports a non-Component helper for generating the yup form validations. Both the helper and the component have a prop/arg for whether to include the phone number.
- The type argument of the
AddressFormFields
component helps guarantee that it will be used in within a formik context that matches those fields
@@ -312,6 +312,7 @@ export const AddressAutocompleteInput = ({ | |||
onChange={onChange} | |||
error={error} | |||
data-testid={dataTestId} | |||
required={!!autocompleteProps.required} |
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.
The address autocomplete input is incorrectly not passing the required prop to its fallback input - likely a bug in the existing shipping route where this input is used, but not likely one many people hit since they generally have an address.
describe("AddressForm", () => { | ||
const mockOnSubmit = jest.fn() | ||
beforeEach(() => { | ||
mockOnSubmit.mockClear() | ||
}) | ||
|
||
describe("without phone number input", () => { |
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 port of the Auction AddressForm.jest.enzyme.tsx file, now with more assertions.
export const fillAddressFormFields = async (address: Partial<Address>) => { | ||
const { country, phoneNumber, ...defaultTextInputs } = address |
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 hopeful this can replace our multiple other fillAddressForm()
helpers and do so in a fast way since we have several test suites completely disable in CI due to timeouts specifically tied to these helpers (see EMI-1685).
export const yupAddressValidator = Yup.object().shape({ | ||
name: Yup.string().required("Full name is required"), | ||
addressLine1: Yup.string().required("Street address is required"), | ||
addressLine2: Yup.string().nullable(), | ||
city: Yup.string().required("City is required"), | ||
postalCode: postalCodeValidator, | ||
region: Yup.string().when("country", { | ||
is: country => ["US", "CA"].includes(country), | ||
then: Yup.string().required("State is required"), | ||
otherwise: Yup.string(), | ||
}), | ||
country: Yup.string().required("Country is required"), | ||
}) |
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.
Copied from our refactored checkout shipping route validations- between this and the user settings>shipping address validations (worth a comparison maybe) I think we can get a single validation schema.
@@ -28,6 +32,9 @@ export const InvoicePaymentForm: React.FC<React.PropsWithChildren<InvoicePayment | |||
<Formik<AddressFormValues> | |||
onSubmit={handleSubmit} | |||
initialValues={{ address: emptyAddress, creditCard: false }} | |||
validationSchema={Yup.object().shape({ | |||
...addressFormFieldsValidator({ withPhoneNumber: false }), |
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 our address form fields validator in a yup schema. strangely this formik context didn't seem to have any validation... maybe because it relied on stripe and we don't actually store any address?
@@ -36,7 +43,7 @@ export const AddressFormWithCreditCard: React.FC<React.PropsWithChildren<unknown | |||
required | |||
/> | |||
|
|||
<AddressForm /> | |||
<AddressFormFields<AddressFormValues> /> |
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 our new AddressFormFields component with the formik type param to mostly guarantee that our context will satisfy those fields*
I say mostly because if you aren't including a phone number then you shouldn't pass the withPhoneNumber
prop. I think we could get fancier with our function component type to give it multiple signatures (if your type doesn't have a phone number, then your withPhoneNumber
prop can't be true. But then you get into the validation schema constructor function which is its own separate thing in a different file and I thought this is too much magic. Maybe a happy medium would be better doc comments in the file.
@@ -44,7 +47,7 @@ export const AddressFormWithCreditCard: React.FC<React.PropsWithChildren<unknown | |||
required | |||
/> | |||
|
|||
<AddressForm /> | |||
<AddressFormFields<AuctionFormValues> withPhoneNumber /> |
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.
And here as well is the auction registration route using our new form withPhoneNumber
. I wondered if i should use the schema constructor helper mentioned earlier in this tour on the formik context here but haven't done it yet.
} | ||
|
||
export const addressFormFieldsValidator = (args: { | ||
withPhoneNumber: boolean |
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.
Should this be typed with Props
right up above?
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.
PR looks great @erikdstock 💯
Only feedback is: The PR title seems a bit misleading considering everything that's going on in here. If we can perhaps summarize it there (for search) that'd be ideal, but otherwise 🍏
The type of this PR is: feat
The changes are relatively small when viewed commit-by-commit, at least for the early ones.
Description
This PR relates to EMI-2196 and completes EMI-2205. It consolidates our Auction + Invoice address forms to use a single
<AddressFormFields />
layout. This component includes its own validation schema and theutils
files in thesrc/Components/Address
has new helpers for working with and testing that. There are new tests to replace Because the phone number input is sometimes not required, it can be controlled with a prop.Because we consolidate forms, we also get US address autocomplete in the invoice form for free (this could also be controlled with a prop if we wanted).
cc @artsy/emerald-devs
Invoice app, before and after.
Invoice form with autocomplete
Followup work
fillAddressFormFields()
created for this specific layout might be more efficient than the multiple similar helpers calledfillAddressForm()
. This migration could therefore help address EMI-1685.cc @artsy/emerald-devs