diff --git a/packages/features/bookings/lib/getBookingResponsesSchema.test.ts b/packages/features/bookings/lib/getBookingResponsesSchema.test.ts index 5e59511c51..556356dd79 100644 --- a/packages/features/bookings/lib/getBookingResponsesSchema.test.ts +++ b/packages/features/bookings/lib/getBookingResponsesSchema.test.ts @@ -1095,7 +1095,7 @@ describe("validate radioInput type field", () => { }); describe("validate url type field", () => { - test(`should fail parsing if invalid url provided`, async ({}) => { + test(`should pass parsing if protocol is missing`, async ({}) => { const schema = getBookingResponsesSchema({ bookingFields: [ { @@ -1121,6 +1121,44 @@ describe("validate url type field", () => { name: "test", url: "www.example.com", }); + // Expect success because our logic now handles missing protocol + 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", + url: "www.example.com", + }); + }); + + test(`should fail parsing if url is truly invalid`, async ({}) => { + const schema = getBookingResponsesSchema({ + bookingFields: [ + { + name: "name", + type: "name", + required: true, + }, + { + name: "email", + type: "email", + required: true, + }, + { + name: "url", + type: "url", + required: true, + }, + ] as z.infer & z.BRAND<"HAS_SYSTEM_FIELDS">, + view: "ALL_VIEWS", + }); + const parsedResponses = await schema.safeParseAsync({ + email: "test@test.com", + name: "test", + url: "http:/nope", + }); expect(parsedResponses.success).toBe(false); if (parsedResponses.success) { throw new Error("Should not reach here"); @@ -1132,6 +1170,7 @@ describe("validate url type field", () => { }) ); }); + test(`should successfully give responses if url type field value is valid`, async ({}) => { const schema = getBookingResponsesSchema({ bookingFields: [ diff --git a/packages/features/form-builder/schema.ts b/packages/features/form-builder/schema.ts index 9856d37533..4ff75aefdd 100644 --- a/packages/features/form-builder/schema.ts +++ b/packages/features/form-builder/schema.ts @@ -403,12 +403,31 @@ export const fieldTypesSchemaMap: Partial< const value = response ?? ""; const urlSchema = z.string().url(); - if (!urlSchema.safeParse(value).success) { + // Check for malformed protocols (missing second slash test case) + if (value.match(/^https?:\/[^\/]/)) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: m("url_validation_error"), }); + return; } + + // 1. Try validating the original value + if (urlSchema.safeParse(value).success) { + return; + } + + // 2. If it failed, try prepending https:// + const valueWithHttps = `https://${value}`; + if (urlSchema.safeParse(valueWithHttps).success) { + return; + } + + // 3. If all attempts fail, throw err + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: m("url_validation_error"), + }); }, }, };