Skip to content

Commit 0eb2c15

Browse files
mixelburgromitg2
andauthored
fix: handle JSON string name field from URL prefill for firstAndLastName variant (calcom#28039)
* fix: handle JSON string name field from URL prefill for firstAndLastName variant * refactoring logic * improve test coverage * remove unnecessary comment --------- Co-authored-by: Maks Pikov <mixelburg@users.noreply.github.com> Co-authored-by: Romit <romitgabani1.work@gmail.com> Co-authored-by: Romit <85230081+romitg2@users.noreply.github.com>
1 parent 9d29055 commit 0eb2c15

2 files changed

Lines changed: 134 additions & 2 deletions

File tree

packages/features/bookings/lib/getBookingResponsesSchema.test.ts

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,7 @@ describe("getBookingResponsesSchema", () => {
329329
);
330330
});
331331

332-
// TODO: Fix this behaviour later
333-
test.skip("`firstAndLastName` variant to `fullName` when passed as JSON string from URL prefill", async () => {
332+
test("`firstAndLastName` variant to `fullName` when passed as JSON string from URL prefill", async () => {
334333
const schema = getBookingResponsesSchema({
335334
bookingFields: [
336335
{
@@ -366,6 +365,126 @@ describe("getBookingResponsesSchema", () => {
366365
);
367366
});
368367

368+
test("JSON string with only firstName (no lastName) from URL prefill", async () => {
369+
const schema = getBookingResponsesSchema({
370+
bookingFields: [
371+
{
372+
name: "name",
373+
type: "name",
374+
required: true,
375+
},
376+
{
377+
name: "email",
378+
type: "email",
379+
required: true,
380+
},
381+
] as z.infer<typeof eventTypeBookingFields> & z.BRAND<"HAS_SYSTEM_FIELDS">,
382+
view: "ALL_VIEWS",
383+
});
384+
const parsedResponses = await schema.safeParseAsync({
385+
name: '{"firstName":"John"}',
386+
email: "john@example.com",
387+
});
388+
389+
expectResponsesToBe(
390+
parsedResponses,
391+
expect.objectContaining({
392+
name: "John",
393+
email: "john@example.com",
394+
})
395+
);
396+
});
397+
398+
test("Invalid JSON string falls back to regular string handling", async () => {
399+
const schema = getBookingResponsesSchema({
400+
bookingFields: [
401+
{
402+
name: "name",
403+
type: "name",
404+
required: true,
405+
},
406+
{
407+
name: "email",
408+
type: "email",
409+
required: true,
410+
},
411+
] as z.infer<typeof eventTypeBookingFields> & z.BRAND<"HAS_SYSTEM_FIELDS">,
412+
view: "ALL_VIEWS",
413+
});
414+
const parsedResponses = await schema.safeParseAsync({
415+
name: "{not valid json}",
416+
email: "john@example.com",
417+
});
418+
419+
expectResponsesToBe(
420+
parsedResponses,
421+
expect.objectContaining({
422+
name: "{not valid json}",
423+
email: "john@example.com",
424+
})
425+
);
426+
});
427+
428+
test("JSON array falls back to regular string handling", async () => {
429+
const schema = getBookingResponsesSchema({
430+
bookingFields: [
431+
{
432+
name: "name",
433+
type: "name",
434+
required: true,
435+
},
436+
{
437+
name: "email",
438+
type: "email",
439+
required: true,
440+
},
441+
] as z.infer<typeof eventTypeBookingFields> & z.BRAND<"HAS_SYSTEM_FIELDS">,
442+
view: "ALL_VIEWS",
443+
});
444+
const parsedResponses = await schema.safeParseAsync({
445+
name: '["John", "Doe"]',
446+
email: "john@example.com",
447+
});
448+
449+
expectResponsesToBe(
450+
parsedResponses,
451+
expect.objectContaining({
452+
name: '["John", "Doe"]',
453+
email: "john@example.com",
454+
})
455+
);
456+
});
457+
458+
test("JSON object without firstName falls back to regular string handling", async () => {
459+
const schema = getBookingResponsesSchema({
460+
bookingFields: [
461+
{
462+
name: "name",
463+
type: "name",
464+
required: true,
465+
},
466+
{
467+
name: "email",
468+
type: "email",
469+
required: true,
470+
},
471+
] as z.infer<typeof eventTypeBookingFields> & z.BRAND<"HAS_SYSTEM_FIELDS">,
472+
view: "ALL_VIEWS",
473+
});
474+
const parsedResponses = await schema.safeParseAsync({
475+
name: '{"name":"John Doe"}',
476+
email: "john@example.com",
477+
});
478+
479+
expectResponsesToBe(
480+
parsedResponses,
481+
expect.objectContaining({
482+
name: '{"name":"John Doe"}',
483+
email: "john@example.com",
484+
})
485+
);
486+
});
487+
369488
test("`fullName` to `firstAndLastName` when there is a lastName(separated by space)", async () => {
370489
const schema = getBookingResponsesSchema({
371490
bookingFields: [

packages/features/form-builder/schema.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,19 @@ export const fieldTypesSchemaMap = {
144144
}
145145

146146
if (typeof response === "string") {
147+
const nameJsonSchema = z.object({
148+
firstName: z.string(),
149+
lastName: z.string().optional().default(""),
150+
});
151+
152+
try {
153+
const parsed = nameJsonSchema.safeParse(JSON.parse(response));
154+
if (parsed.success) {
155+
return preprocessNameFieldDataWithVariant(correctedVariant, parsed.data);
156+
}
157+
} catch {
158+
// if invalid JSON, then treat as regular string
159+
}
147160
return preprocessNameFieldDataWithVariant(correctedVariant, response);
148161
}
149162

0 commit comments

Comments
 (0)