mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-21 13:40:31 -06:00
Compare commits
1 Commits
4.1.0
...
cursor/han
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cfeea0073 |
@@ -167,6 +167,17 @@ export const UploadContactsCSVButton = ({
|
||||
const transformedCsvData = csvResponse.map((record) => {
|
||||
const newRecord: Record<string, string> = {};
|
||||
Object.entries(record).forEach(([key, value]) => {
|
||||
// Normalize default attribute keys to their canonical form for case-insensitive matching
|
||||
const defaultAttributeKeysMap: Record<string, string> = {
|
||||
userid: "userId",
|
||||
firstname: "firstName",
|
||||
lastname: "lastName",
|
||||
email: "email",
|
||||
language: "language",
|
||||
};
|
||||
const keyLower = key.toLowerCase();
|
||||
const normalizedKey = defaultAttributeKeysMap[keyLower] || key;
|
||||
|
||||
// if the key is in the attribute map, we wanna replace it
|
||||
if (attributeMap[key]) {
|
||||
const attrKeyId = attributeMap[key];
|
||||
@@ -178,7 +189,7 @@ export const UploadContactsCSVButton = ({
|
||||
newRecord[attrKeyId] = value;
|
||||
}
|
||||
} else {
|
||||
newRecord[key] = value;
|
||||
newRecord[normalizedKey] = value;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -244,6 +255,8 @@ export const UploadContactsCSVButton = ({
|
||||
}, [error]);
|
||||
|
||||
// Function to download an example CSV
|
||||
// Note: The example uses canonical casing for default attributes (email, userId, firstName, lastName, language)
|
||||
// The upload process is case-insensitive for these attributes (e.g., "Language" will be normalized to "language")
|
||||
const handleDownloadExampleCSV = () => {
|
||||
const exampleData = [
|
||||
{ email: "user1@example.com", userId: "1001", firstName: "John", lastName: "Doe" },
|
||||
|
||||
@@ -319,6 +319,54 @@ describe("createContactsFromCSV", () => {
|
||||
createContactsFromCSV(csvData, environmentId, "skip", { email: "email", name: "name" })
|
||||
).rejects.toThrow(genericError);
|
||||
});
|
||||
|
||||
test("handles case-insensitive attribute keys (language, userId, firstName, lastName, email)", async () => {
|
||||
vi.mocked(prisma.contact.findMany).mockResolvedValue([]);
|
||||
vi.mocked(prisma.contactAttribute.findMany).mockResolvedValue([]);
|
||||
vi.mocked(prisma.contactAttributeKey.findMany)
|
||||
.mockResolvedValueOnce([])
|
||||
.mockResolvedValueOnce([
|
||||
{ key: "email", id: "id-email" },
|
||||
{ key: "userId", id: "id-userId" },
|
||||
{ key: "firstName", id: "id-firstName" },
|
||||
{ key: "lastName", id: "id-lastName" },
|
||||
{ key: "language", id: "id-language" },
|
||||
] as any);
|
||||
vi.mocked(prisma.contactAttributeKey.createMany).mockResolvedValue({ count: 5 });
|
||||
vi.mocked(prisma.contact.create).mockResolvedValue({
|
||||
id: "c1",
|
||||
environmentId,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
attributes: [
|
||||
{ attributeKey: { key: "email" }, value: "john@example.com" },
|
||||
{ attributeKey: { key: "userId" }, value: "user123" },
|
||||
{ attributeKey: { key: "firstName" }, value: "John" },
|
||||
{ attributeKey: { key: "lastName" }, value: "Doe" },
|
||||
{ attributeKey: { key: "language" }, value: "en" },
|
||||
],
|
||||
} as any);
|
||||
// CSV data with normalized keys (already handled by client-side component)
|
||||
const csvData = [
|
||||
{
|
||||
email: "john@example.com",
|
||||
userId: "user123",
|
||||
firstName: "John",
|
||||
lastName: "Doe",
|
||||
language: "en",
|
||||
},
|
||||
];
|
||||
const result = await createContactsFromCSV(csvData, environmentId, "skip", {
|
||||
email: "email",
|
||||
userId: "userId",
|
||||
firstName: "firstName",
|
||||
lastName: "lastName",
|
||||
language: "language",
|
||||
});
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result[0].id).toBe("c1");
|
||||
expect(prisma.contactAttributeKey.createMany).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildContactWhereClause", () => {
|
||||
|
||||
Reference in New Issue
Block a user