From 5ce96c77045c58de98f41324659c76244ac94b5f Mon Sep 17 00:00:00 2001 From: Hariom Balhara Date: Tue, 6 Aug 2024 16:35:08 +0530 Subject: [PATCH] fix: Prefill of Phone type option field (#16086) --- .../lib/getBookingResponsesSchema.test.ts | 99 ++++++++++++++++++- .../bookings/lib/getBookingResponsesSchema.ts | 14 ++- 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/packages/features/bookings/lib/getBookingResponsesSchema.test.ts b/packages/features/bookings/lib/getBookingResponsesSchema.test.ts index c40712030c..8e0529773a 100644 --- a/packages/features/bookings/lib/getBookingResponsesSchema.test.ts +++ b/packages/features/bookings/lib/getBookingResponsesSchema.test.ts @@ -990,11 +990,108 @@ describe("getBookingResponsesSchema", () => { test.todo("select"); test.todo("textarea"); test.todo("number"); - test.todo("radioInput"); test.todo("checkbox"); test.todo("radio"); test.todo("boolean"); }); + +describe("validate radioInput type field", () => { + test(`should fail parsing if invalid phone number is provided`, async ({}) => { + const schema = getBookingResponsesSchema({ + bookingFields: [ + { + name: "name", + type: "name", + required: true, + }, + { + name: "email", + type: "email", + required: true, + }, + { + name: "radioInput", + type: "radioInput", + required: true, + optionsInputs: { + phone: { + type: "phone", + }, + }, + }, + ] as z.infer & z.BRAND<"HAS_SYSTEM_FIELDS">, + view: "ALL_VIEWS", + }); + const parsedResponses = await schema.safeParseAsync({ + email: "test@test.com", + name: "test", + radioInput: JSON.stringify({ + value: "phone", + optionValue: " 9999999999", + }), + }); + expect(parsedResponses.success).toBe(false); + if (parsedResponses.success) { + throw new Error("Should not reach here"); + } + expect(parsedResponses.error.issues[0]).toEqual( + expect.objectContaining({ + code: "custom", + message: `{radioInput}${CUSTOM_PHONE_VALIDATION_ERROR_MSG}`, + }) + ); + }); + + test(`should correctly handle space in the beginning of phone number which could come from a + in prefill URL`, async ({}) => { + const schema = getBookingResponsesSchema({ + bookingFields: [ + { + name: "name", + type: "name", + required: true, + }, + { + name: "email", + type: "email", + required: true, + }, + { + name: "radioInput", + type: "radioInput", + required: true, + optionsInputs: { + // A field of type phone + randomField: { + type: "phone", + }, + }, + }, + ] as z.infer & z.BRAND<"HAS_SYSTEM_FIELDS">, + view: "ALL_VIEWS", + }); + const parsedResponses = await schema.safeParseAsync({ + email: "test@test.com", + name: "test", + radioInput: JSON.stringify({ + value: "randomField", + optionValue: " 919999999999", + }), + }); + expect(parsedResponses.success).toBe(true); + if (!parsedResponses.success) { + throw new Error("Should not reach here"); + } + expect(parsedResponses.data).toEqual({ + email: "test@test.com", + name: "test", + radioInput: { + value: "randomField", + optionValue: "+919999999999", + }, + }); + }); +}); + describe("validate url type field", () => { test(`should fail parsing if invalid url provided`, async ({}) => { const schema = getBookingResponsesSchema({ diff --git a/packages/features/bookings/lib/getBookingResponsesSchema.ts b/packages/features/bookings/lib/getBookingResponsesSchema.ts index 31b3c732f0..6260bbc126 100644 --- a/packages/features/bookings/lib/getBookingResponsesSchema.ts +++ b/packages/features/bookings/lib/getBookingResponsesSchema.ts @@ -15,6 +15,11 @@ export const bookingResponsesDbSchema = z.record(dbReadResponseSchema); const catchAllSchema = bookingResponsesDbSchema; +const ensureValidPhoneNumber = (value: string) => { + // + in URL could be replaced with space, so we need to replace it back + // Replace the space(s) in the beginning with + as it is supposed to be provided in the beginning only + return value.replace(/^ +/, "+"); +}; export const getBookingResponsesPartialSchema = ({ bookingFields, view }: CommonParams) => { const schema = bookingResponses.unwrap().partial().and(catchAllSchema); @@ -89,11 +94,14 @@ function preprocess({ try { parsedValue = JSON.parse(value); } catch (e) {} + const optionsInputs = field.optionsInputs; + const optionInputField = optionsInputs?.[parsedValue.value]; + if (optionInputField && optionInputField.type === "phone") { + parsedValue.optionValue = ensureValidPhoneNumber(parsedValue.optionValue); + } newResponses[field.name] = parsedValue; } else if (field.type === "phone") { - // + in URL could be replaced with space, so we need to replace it back - // Replace the space(s) in the beginning with + as it is supposed to be provided in the beginning only - newResponses[field.name] = value.replace(/^ +/, "+"); + newResponses[field.name] = ensureValidPhoneNumber(value); } else { newResponses[field.name] = value; }