diff --git a/apps/web/src/utils/__tests__/upload.test.ts b/apps/web/src/utils/__tests__/upload.test.ts index 46fdc942a..869463600 100644 --- a/apps/web/src/utils/__tests__/upload.test.ts +++ b/apps/web/src/utils/__tests__/upload.test.ts @@ -536,6 +536,19 @@ describe('Zod3', () => { it('should leave out a field the record does not mention', async () => { await expect(processItems('RECORD_ARRAY(name:item1)')).resolves.toMatchObject([{ items: [{ name: 'item1' }] }]); }); + + it('should reject a record array missing its closing parenthesis, rather than dropping its last character', async () => { + await expectRejection( + processItems('RECORD_ARRAY(name:item1,quantity:12'), + "Syntax error in RECORD_ARRAY declaration: RECORD_ARRAY(name:item1,quantity:12 at column name: 'items' and row number '1'" + ); + }); + + it('should keep a colon inside a record array value, splitting each field on its first colon only', async () => { + await expect(processItems('RECORD_ARRAY(name:10:30,quantity:1;)')).resolves.toMatchObject([ + { items: [{ name: '10:30', quantity: 1 }] } + ]); + }); }); }); }); diff --git a/apps/web/src/utils/upload.ts b/apps/web/src/utils/upload.ts index 56240b564..6e3d1f714 100644 --- a/apps/web/src/utils/upload.ts +++ b/apps/web/src/utils/upload.ts @@ -141,7 +141,7 @@ function extractRecordArrayEntry(entry: string): { [key: string]: string }[] { entry = entry.trim(); const opening = 'RECORD_ARRAY('; const closing = ')'; - if (!entry.startsWith(opening) && !entry.endsWith(closing)) { + if (!entry.startsWith(opening) || !entry.endsWith(closing)) { throw new UploadError({ en: `Syntax error in RECORD_ARRAY declaration: ${entry}`, fr: `Erreur de syntaxe dans la déclaration RECORD_ARRAY : ${entry}` @@ -165,15 +165,17 @@ function extractRecordArrayEntry(entry: string): { [key: string]: string }[] { } const records: { [key: string]: string } = {}; recordsList.forEach((rawRecord, i) => { - const [recordKey, recordValue] = rawRecord.split(':').map((s) => s.trim()); - if (!recordKey) { + const separatorIndex = rawRecord.indexOf(':'); + const recordKey = rawRecord.slice(0, separatorIndex).trim(); + const recordValue = rawRecord.slice(separatorIndex + 1).trim(); + if (separatorIndex === -1 || !recordKey) { throw new UploadError({ en: `Malformed record at index ${i}`, fr: `Enregistrement mal formé à l'index ${i}` }); } //recordValue can be empty if the value is optional - records[recordKey] = recordValue!; + records[recordKey] = recordValue; }); return records; });