Skip to content

Commit 32f70c3

Browse files
authored
ref: Remove Postal Code complexity on payment form (#87224)
This PR aims to reduce some complexity on the Credit Card Form by deleting the postal code field and tapping into the postal code field on the stripe form directly. Looking back, the change was made 7+ years ago to add that separate functionality due to some weird validation errors on Stripe's end; but I think since then we can reasonably assume that Stripe has probably made some updates and fixed those updates. And if not, this will be easy enough to revert 😅 Had to go digging but here's the original commit: ![Screenshot 2025-03-17 at 11 56 56 AM](https://github.com/user-attachments/assets/e1b24c8e-15d2-45a7-b1e4-bd8d556de79c) **LOCAL Testing** https://github.com/user-attachments/assets/1f1e7285-9c26-484c-b637-53ea36dcbf1c **Checkout Flow** https://github.com/user-attachments/assets/894cd805-46dd-4c0f-983b-101b7259eb59 **Postal Code Validation** ![Screenshot 2025-03-17 at 2 00 56 PM](https://github.com/user-attachments/assets/c213ecf6-feff-4db2-b7ea-93d2f9a0fe15) Closes #85040 <!-- Sentry employees and contractors can delete or ignore the following. --> ### Legal Boilerplate Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.
1 parent af0781f commit 32f70c3

File tree

4 files changed

+3
-95
lines changed

4 files changed

+3
-95
lines changed

static/gsApp/components/creditCardForm.tsx

-35
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {Alert} from 'sentry/components/core/alert';
88
import {Button} from 'sentry/components/core/button';
99
import {Input} from 'sentry/components/core/input';
1010
import FieldGroup from 'sentry/components/forms/fieldGroup';
11-
import TextField from 'sentry/components/forms/fields/textField';
1211
import ExternalLink from 'sentry/components/links/externalLink';
1312
import LoadingIndicator from 'sentry/components/loadingIndicator';
1413
import {NODE_ENV} from 'sentry/constants';
@@ -96,7 +95,6 @@ function CreditCardForm({
9695
referrer,
9796
}: Props) {
9897
const theme = useTheme();
99-
const [postalCode, setPostalCode] = useState('');
10098
const [busy, setBusy] = useState(false);
10199
const [stripe, setStripe] = useState<stripe.Stripe>();
102100
const [cardElement, setCardElement] = useState<stripe.elements.Element>();
@@ -141,7 +139,6 @@ function CreditCardForm({
141139
fonts: [{family: 'Rubik', src: `url(${rubikFontPath})`, weight: '400'}],
142140
});
143141
const stripeCardElement = stripeElements.create('card', {
144-
hidePostalCode: true,
145142
style: stripeElementStyles,
146143
});
147144

@@ -164,9 +161,6 @@ function CreditCardForm({
164161
setBusy(true);
165162

166163
const validationErrors: string[] = [];
167-
if (postalCode === '') {
168-
validationErrors.push(t('Postal code is required.'));
169-
}
170164

171165
if (!stripe || !cardElement) {
172166
return;
@@ -182,19 +176,6 @@ function CreditCardForm({
182176
onCancel?.();
183177
}
184178

185-
function handlePostalCodeChange(value: string) {
186-
setPostalCode(value);
187-
if (cardElement) {
188-
cardElement.update({value: {postalCode: value}});
189-
}
190-
}
191-
function handlePostalCodeBlur(value: string) {
192-
setPostalCode(value);
193-
if (cardElement) {
194-
cardElement.update({value: {postalCode: value}});
195-
}
196-
}
197-
198179
function handleErrorRetry(event: React.MouseEvent) {
199180
event.preventDefault();
200181
errorRetry?.();
@@ -243,18 +224,6 @@ function CreditCardForm({
243224
<div ref={stripeMount} />
244225
</FormControl>
245226
</StyledField>
246-
<StyledTextField
247-
required
248-
stacked
249-
flexibleControlStateSize
250-
inline={false}
251-
maxLength={12}
252-
name="postal"
253-
label={t('Postal Code')}
254-
value={postalCode}
255-
onChange={handlePostalCodeChange}
256-
onBlur={handlePostalCodeBlur}
257-
/>
258227

259228
<Info>
260229
<small>
@@ -304,10 +273,6 @@ const StyledField = styled(FieldGroup)`
304273
padding-top: 0;
305274
`;
306275

307-
const StyledTextField = styled(TextField)`
308-
${fieldCss};
309-
`;
310-
311276
const Info = styled('p')`
312277
${fieldCss};
313278
margin-bottom: ${space(3)};

static/gsApp/views/amCheckout/steps/addPaymentMethod.spec.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ describe('AddPaymentMethod', function () {
148148
await waitFor(() => expect(setupIntent).toHaveBeenCalled());
149149

150150
expect(screen.getByLabelText('Card Details')).toBeInTheDocument();
151-
expect(screen.getByRole('textbox', {name: 'Postal Code'})).toBeInTheDocument();
152151
expect(screen.getByRole('button', {name: 'Continue'})).toBeInTheDocument();
153152
});
154153

static/gsApp/views/invoiceDetails/paymentForm.spec.tsx

+3-16
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ import {OrganizationFixture} from 'sentry-fixture/organization';
33

44
import {InvoiceFixture} from 'getsentry-test/fixtures/invoice';
55
import {
6-
act,
76
cleanup,
8-
fireEvent,
97
render,
108
screen,
9+
userEvent,
1110
waitFor,
1211
} from 'sentry-test/reactTestingLibrary';
1312

@@ -126,14 +125,8 @@ describe('InvoiceDetails > Payment Form', function () {
126125
expect(error).toBeInTheDocument();
127126

128127
// Submit the form anyways
129-
const postalCode = screen.getByRole('textbox', {name: 'Postal Code'});
130-
act(() => {
131-
fireEvent.change(postalCode, {target: {value: '90210'}});
132-
});
133128
const button = screen.getByRole('button', {name: 'Pay Now'});
134-
act(() => {
135-
fireEvent.click(button);
136-
});
129+
await userEvent.click(button);
137130

138131
// Should show an error as our intent never loaded.
139132
error = screen.getByText(/Cannot complete your payment/);
@@ -162,14 +155,8 @@ describe('InvoiceDetails > Payment Form', function () {
162155

163156
expect(screen.getByText('Pay Invoice')).toBeInTheDocument();
164157

165-
const postalCode = screen.getByRole('textbox', {name: 'Postal Code'});
166-
act(() => {
167-
fireEvent.change(postalCode, {target: {value: '90210'}});
168-
});
169158
const button = screen.getByRole('button', {name: 'Pay Now'});
170-
act(() => {
171-
fireEvent.click(button);
172-
});
159+
await userEvent.click(button);
173160
await waitFor(() => expect(reloadInvoice).toHaveBeenCalled());
174161
expect(reloadInvoice).toHaveBeenCalled();
175162
});

static/gsApp/views/subscriptionPage/billingDetails.spec.tsx

-43
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,6 @@ describe('Subscription > BillingDetails', function () {
216216
const modal = await screen.findByRole('dialog');
217217
const inModal = within(modal);
218218

219-
// Postal code input is not handled by Stripe elements. We need to fill it
220-
// before submit will pass to Stripe
221-
await userEvent.type(inModal.getByRole('textbox', {name: 'Postal Code'}), '94107');
222-
223219
// Save the updated credit card details
224220
await userEvent.click(inModal.getByRole('button', {name: 'Save Changes'}));
225221
await waitForModalToHide();
@@ -243,41 +239,6 @@ describe('Subscription > BillingDetails', function () {
243239
});
244240
});
245241

246-
it('rejects update credit card if zip code is not included with setupintent', async function () {
247-
const mock = MockApiClient.addMockResponse({
248-
url: `/customers/${organization.slug}/`,
249-
method: 'PUT',
250-
});
251-
MockApiClient.addMockResponse({
252-
url: `/organizations/${organization.slug}/payments/setup/`,
253-
method: 'POST',
254-
body: {
255-
id: '123',
256-
clientSecret: 'seti_abc123',
257-
status: 'require_payment_method',
258-
lastError: null,
259-
},
260-
});
261-
262-
render(
263-
<BillingDetailsView
264-
organization={organization}
265-
subscription={subscription}
266-
location={router.location}
267-
/>
268-
);
269-
270-
await screen.findByRole('textbox', {name: /street address 1/i});
271-
await userEvent.click(screen.getByRole('button', {name: 'Update card'}));
272-
273-
renderGlobalModal();
274-
const modal = await screen.findByRole('dialog');
275-
await userEvent.click(within(modal).getByRole('button', {name: 'Save Changes'}));
276-
277-
expect(modal).toHaveTextContent('Postal code is required');
278-
expect(mock).not.toHaveBeenCalledWith();
279-
});
280-
281242
it('shows an error if the setupintent creation fails', async function () {
282243
MockApiClient.addMockResponse({
283244
url: `/organizations/${organization.slug}/payments/setup/`,
@@ -330,10 +291,6 @@ describe('Subscription > BillingDetails', function () {
330291
const modal = await screen.findByRole('dialog');
331292
const inModal = within(modal);
332293

333-
// Postal code input is not handled by Stripe elements. We need to fill it
334-
// before submit will pass to Stripe
335-
await userEvent.type(inModal.getByRole('textbox', {name: 'Postal Code'}), '94107');
336-
337294
// Save the updated credit card details
338295
await userEvent.click(inModal.getByRole('button', {name: 'Save Changes'}));
339296

0 commit comments

Comments
 (0)