* mv PaymentPage to web * mv 2 more components to web * refactor * update imports * mv * revert * fix * fix * update * migrate relevant test too * move setup components to web from appstore * move wipemycalother * mv * fix typechecks * mv more routing forms components * fix * fix * fix * fix: resolve type errors in SingleForm.tsx after migration - Updated SingleFormComponentProps type to include enriched form properties - Added proper typing for user, team, nonOrgUsername, nonOrgTeamslug, userOrigin, teamOrigin - Fixes type errors that occurred after migrating SingleForm.tsx from packages/app-store/routing-forms/components/ - Resolves both SingleForm.tsx and TestForm.tsx type errors Co-Authored-By: benny@cal.com <sldisek783@gmail.com> * delete * refactors * fix * fix * fix * remove usage of trpc client from OmniInstallAppButton.tsx * fix test * import only type * fix test * remove trpc package from appstore package.json * remove remaining trpc usage * update test * fix type checks * fix errors * fix * make it error * nit --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
354 lines
9.9 KiB
TypeScript
354 lines
9.9 KiB
TypeScript
import { v4 as uuidv4 } from "uuid";
|
|
import { describe, it, expect } from "vitest";
|
|
|
|
import { getUrlSearchParamsToForward } from "./getUrlSearchParamsToForward";
|
|
|
|
function fromEntriesWithDuplicateKeys(entries: IterableIterator<[string, string]> | null) {
|
|
const result: Record<string, string | string[]> = {};
|
|
|
|
if (entries === null) {
|
|
return result;
|
|
}
|
|
|
|
// Consider setting atleast ES2015 as target
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
for (const [key, value] of entries) {
|
|
if (result.hasOwnProperty(key)) {
|
|
let currentValue = result[key];
|
|
if (!Array.isArray(currentValue)) {
|
|
currentValue = [currentValue];
|
|
}
|
|
currentValue.push(value);
|
|
result[key] = currentValue;
|
|
} else {
|
|
result[key] = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
describe("getUrlSearchParamsToForward", () => {
|
|
it("should build query params from response correctly when identifier is present in fields", () => {
|
|
const field1Id = uuidv4();
|
|
const field2Id = uuidv4();
|
|
const formResponse = {
|
|
[field1Id]: { value: "value1", label: "Field 1" },
|
|
[field2Id]: { value: ["option1", "option2"], label: "Field 2" },
|
|
};
|
|
|
|
const fields = [
|
|
{ id: field1Id, identifier: "f1", type: "text", label: "Field 1" },
|
|
{
|
|
id: field2Id,
|
|
identifier: "f2",
|
|
label: "Field 2",
|
|
type: "multiselect",
|
|
options: [
|
|
{ id: "option1", label: "Option 1" },
|
|
{ id: "option2", label: "Option 2" },
|
|
],
|
|
},
|
|
];
|
|
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
const expectedParams = {
|
|
f1: "value1",
|
|
f2: ["Option 1", "Option 2"],
|
|
query1: "value1",
|
|
query2: "value2",
|
|
"cal.routingFormResponseId": "1",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse,
|
|
fields,
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: null,
|
|
formResponseId: 1,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: null,
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should build query params from response correctly when identifier is not present in fields. Should fallback to label", () => {
|
|
const field1Id = uuidv4();
|
|
const field2Id = uuidv4();
|
|
const formResponse = {
|
|
[field1Id]: { value: "value1" },
|
|
[field2Id]: { value: "value2" },
|
|
};
|
|
|
|
const fields = [
|
|
{ id: field1Id, label: "Field 1", type: "text" },
|
|
{ id: field2Id, label: "Field 2", type: "text" },
|
|
];
|
|
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
|
|
const expectedParams = {
|
|
"Field 1": "value1",
|
|
"Field 2": "value2",
|
|
query1: "value1",
|
|
query2: "value2",
|
|
"cal.routingFormResponseId": "1",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse,
|
|
fields,
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: null,
|
|
formResponseId: 1,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: null,
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should handle select fields correctly when options have id set", () => {
|
|
const field1Id = uuidv4();
|
|
const field2Id = uuidv4();
|
|
const formResponse = {
|
|
[field1Id]: { value: "Option 1" },
|
|
[field2Id]: { value: ["Option 1", "Option 2"] },
|
|
};
|
|
|
|
const fields = [
|
|
{
|
|
id: field1Id,
|
|
label: "Field 1",
|
|
type: "select",
|
|
options: [
|
|
{ id: "option1", label: "Option 1" },
|
|
{ id: "option2", label: "Option 2" },
|
|
],
|
|
},
|
|
{
|
|
id: field2Id,
|
|
label: "Field 2",
|
|
type: "multiselect",
|
|
options: [
|
|
{ id: "option1", label: "Option 1" },
|
|
{ id: "option2", label: "Option 2" },
|
|
{ id: "option3", label: "Option 3" },
|
|
],
|
|
},
|
|
];
|
|
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
|
|
const expectedParams = {
|
|
"Field 1": "Option 1",
|
|
"Field 2": ["Option 1", "Option 2"],
|
|
query1: "value1",
|
|
query2: "value2",
|
|
"cal.routingFormResponseId": "1",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse,
|
|
fields,
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: null,
|
|
formResponseId: 1,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: null,
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should handle select fields correctly when options have no id set(Legacy options)", () => {
|
|
const field1Id = uuidv4();
|
|
const field2Id = uuidv4();
|
|
const formResponse = {
|
|
[field1Id]: { value: "Option 1" },
|
|
[field2Id]: { value: ["Option 1", "Option 2"] },
|
|
};
|
|
|
|
const fields = [
|
|
{
|
|
id: field1Id,
|
|
label: "Field 1",
|
|
type: "select",
|
|
options: [
|
|
{ id: null, label: "Option 1" },
|
|
{ id: null, label: "Option 2" },
|
|
],
|
|
},
|
|
{
|
|
id: field2Id,
|
|
label: "Field 2",
|
|
type: "multiselect",
|
|
options: [
|
|
{ id: "option1", label: "Option 1" },
|
|
{ id: "option2", label: "Option 2" },
|
|
{ id: "option3", label: "Option 3" },
|
|
],
|
|
},
|
|
];
|
|
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
|
|
const expectedParams = {
|
|
"Field 1": "Option 1",
|
|
"Field 2": ["Option 1", "Option 2"],
|
|
query1: "value1",
|
|
query2: "value2",
|
|
"cal.routingFormResponseId": "1",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse,
|
|
fields,
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: null,
|
|
formResponseId: 1,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: null,
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should handle number values correctly", () => {
|
|
const field1Id = uuidv4();
|
|
const response = {
|
|
[field1Id]: { value: 123 },
|
|
};
|
|
|
|
const fields = [{ id: field1Id, label: "Field 1", type: "number" }];
|
|
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
const expectedParams = {
|
|
"Field 1": "123",
|
|
query1: "value1",
|
|
query2: "value2",
|
|
"cal.routingFormResponseId": "1",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse: response,
|
|
fields,
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: null,
|
|
formResponseId: 1,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: null,
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should add cal.skipContactOwner when attributeRoutingConfig.skipContactOwner is true", () => {
|
|
const field1Id = uuidv4();
|
|
const field2Id = uuidv4();
|
|
const formResponse = {
|
|
[field1Id]: { value: "value1", label: "Field 1" },
|
|
[field2Id]: { value: ["option1", "option2"], label: "Field 2" },
|
|
};
|
|
|
|
const fields = [
|
|
{ id: field1Id, identifier: "f1", type: "text", label: "Field 1" },
|
|
{
|
|
id: field2Id,
|
|
identifier: "f2",
|
|
label: "Field 2",
|
|
type: "multiselect",
|
|
options: [
|
|
{ id: "option1", label: "Option 1" },
|
|
{ id: "option2", label: "Option 2" },
|
|
],
|
|
},
|
|
];
|
|
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
const expectedParams = {
|
|
f1: "value1",
|
|
f2: ["Option 1", "Option 2"],
|
|
query1: "value1",
|
|
query2: "value2",
|
|
"cal.routingFormResponseId": "1",
|
|
"cal.skipContactOwner": "true",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse,
|
|
fields,
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: null,
|
|
formResponseId: 1,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: {
|
|
skipContactOwner: true,
|
|
},
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
|
|
it("should add cal.routedTeamMemberIds to query params", () => {
|
|
const field1Id = uuidv4();
|
|
const field2Id = uuidv4();
|
|
const formResponse = {
|
|
[field1Id]: { value: "value1", label: "Field 1" },
|
|
[field2Id]: { value: ["option1", "option2"], label: "Field 2" },
|
|
};
|
|
|
|
const fields = [
|
|
{ id: field1Id, identifier: "f1", type: "text", label: "Field 1" },
|
|
{
|
|
id: field2Id,
|
|
identifier: "f2",
|
|
label: "Field 2",
|
|
type: "multiselect",
|
|
options: [
|
|
{ id: "option1", label: "Option 1" },
|
|
{ id: "option2", label: "Option 2" },
|
|
],
|
|
},
|
|
];
|
|
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
const expectedParams = {
|
|
f1: "value1",
|
|
f2: ["Option 1", "Option 2"],
|
|
query1: "value1",
|
|
query2: "value2",
|
|
"cal.routingFormResponseId": "1",
|
|
"cal.routedTeamMemberIds": "1,2",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse,
|
|
fields,
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: [1, 2],
|
|
formResponseId: 1,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: null,
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
|
|
describe("Dry Run", () => {
|
|
it("should add cal.routingFormResponseId=0 when formResponseId is 0", () => {
|
|
const searchParams = new URLSearchParams("?query1=value1&query2=value2");
|
|
const expectedParams = {
|
|
"cal.routingFormResponseId": "0",
|
|
query1: "value1",
|
|
query2: "value2",
|
|
};
|
|
|
|
const result = getUrlSearchParamsToForward({
|
|
formResponse: {},
|
|
fields: [],
|
|
searchParams,
|
|
teamMembersMatchingAttributeLogic: null,
|
|
formResponseId: 0,
|
|
queuedFormResponseId: null,
|
|
attributeRoutingConfig: null,
|
|
});
|
|
expect(fromEntriesWithDuplicateKeys(result.entries())).toEqual(expectedParams);
|
|
});
|
|
});
|
|
});
|