From 986ea33bbb1f11cf133c938b3fd33e257013ad18 Mon Sep 17 00:00:00 2001 From: melton-jason Date: Mon, 13 May 2024 13:14:29 -0500 Subject: [PATCH 1/2] Handle empty row case Fixes #4910 --- .../js_src/lib/components/FormParse/index.ts | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/FormParse/index.ts b/specifyweb/frontend/js_src/lib/components/FormParse/index.ts index 159c0189feb..d06d4abd663 100644 --- a/specifyweb/frontend/js_src/lib/components/FormParse/index.ts +++ b/specifyweb/frontend/js_src/lib/components/FormParse/index.ts @@ -494,33 +494,7 @@ export async function parseFormDefinition( ? getColumnDefinitions(viewDefinition) : directColumnDefinitions ), - await Promise.all( - rows.map(async (row, index) => { - const context = getLogContext(); - pushContext({ - type: 'Child', - tagName: 'row', - extras: { row: index + 1 }, - }); - - const data = await Promise.all( - row.children.cell?.map(async (cell, index) => { - const context = getLogContext(); - pushContext({ - type: 'Child', - tagName: 'cell', - extras: { cell: index + 1 }, - }); - const data = await parseFormCell(table, cell); - - setLogContext(context); - return data; - }) - ); - setLogContext(context); - return data ?? []; - }) - ), + await parseRows(rows, table), table ); @@ -571,6 +545,38 @@ const getColumnDefinition = ( typeof os === 'string' ? getParsedAttribute(child, 'os') === os : true )?.text; +const parseRows = async ( + rawRows: RA, + table: SpecifyTable +): Promise>> => + Promise.all( + rawRows.map(async (row, index) => { + const context = getLogContext(); + pushContext({ + type: 'Child', + tagName: 'row', + extras: { row: index + 1 }, + }); + + const data = await Promise.all( + (row.children.cell ?? []).map(async (cell, index) => { + const context = getLogContext(); + pushContext({ + type: 'Child', + tagName: 'cell', + extras: { cell: index + 1 }, + }); + const data = await parseFormCell(table, cell); + + setLogContext(context); + return data; + }) + ); + setLogContext(context); + return data ?? []; + }) + ); + export const exportsForTests = { views, parseViewDefinitions, From 131ad7b58b11c05a58374f6ab5b4704e8f90956e Mon Sep 17 00:00:00 2001 From: melton-jason Date: Mon, 13 May 2024 13:53:59 -0500 Subject: [PATCH 2/2] Write test for parseRows function --- .../FormParse/__tests__/index.test.ts | 103 ++++++++++++++++++ .../js_src/lib/components/FormParse/index.ts | 1 + 2 files changed, 104 insertions(+) diff --git a/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts b/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts index 15096887062..eefe1c335ae 100644 --- a/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts +++ b/specifyweb/frontend/js_src/lib/components/FormParse/__tests__/index.test.ts @@ -30,6 +30,7 @@ const { parseFormTableColumns, getColumnDefinitions, getColumnDefinition, + parseRows, } = exportsForTests; requireContext(); @@ -529,3 +530,105 @@ theories(getColumnDefinition, [ out: 'B', }, ]); + +const testRows = ` + + + + + + + + + + + + + + + +`; + +test('parseRows', async () => { + const viewDef = xml(testRows); + const rowsContainer = viewDef.children.rows[0]; + const rawRows = rowsContainer?.children?.row ?? []; + + await expect(parseRows(rawRows, tables.CollectingEvent)).resolves.toEqual([ + [ + { + align: 'right', + ariaLabel: undefined, + colSpan: 1, + fieldNames: undefined, + id: undefined, + labelForCellId: 'tt', + text: 'test', + title: undefined, + type: 'Label', + verticalAlign: 'center', + visible: true, + }, + ], + [ + { + align: 'left', + ariaLabel: undefined, + colSpan: 2, + fieldDefinition: { + defaultValue: undefined, + isReadOnly: false, + max: undefined, + maxLength: undefined, + min: undefined, + minLength: undefined, + step: undefined, + type: 'Text', + }, + fieldNames: ['stationFieldNumber'], + id: 'tt', + isRequired: false, + type: 'Field', + verticalAlign: 'center', + visible: true, + }, + { + align: 'left', + ariaLabel: undefined, + colSpan: 1, + fieldDefinition: { + defaultValue: undefined, + isReadOnly: false, + label: '2', + printOnSave: false, + type: 'Checkbox', + }, + fieldNames: ['collectingTrip', 'text1'], + id: undefined, + isRequired: false, + type: 'Field', + verticalAlign: 'center', + visible: true, + }, + ], + [], + [ + { + align: 'left', + ariaLabel: undefined, + colSpan: 1, + fieldNames: ['collectors'], + formType: 'formTable', + icon: undefined, + id: 'dt', + isButton: false, + isCollapsed: false, + sortField: undefined, + type: 'SubView', + verticalAlign: 'stretch', + viewName: 'Collectors', + visible: true, + }, + ], + ]); +}); diff --git a/specifyweb/frontend/js_src/lib/components/FormParse/index.ts b/specifyweb/frontend/js_src/lib/components/FormParse/index.ts index d06d4abd663..a960801f96f 100644 --- a/specifyweb/frontend/js_src/lib/components/FormParse/index.ts +++ b/specifyweb/frontend/js_src/lib/components/FormParse/index.ts @@ -585,4 +585,5 @@ export const exportsForTests = { parseFormTableColumns, getColumnDefinitions, getColumnDefinition, + parseRows, };