@@ -1041,3 +1041,132 @@ describe('PercentCellRenderer progress-type fields', () => {
10411041 expect ( bar ) . toHaveAttribute ( 'aria-valuenow' , '50' ) ;
10421042 } ) ;
10431043} ) ;
1044+
1045+ // =========================================================================
1046+ // Object value safety (coerceToSafeValue) — prevents React error #310
1047+ // =========================================================================
1048+ import {
1049+ NumberCellRenderer ,
1050+ CurrencyCellRenderer ,
1051+ FormulaCellRenderer ,
1052+ coerceToSafeValue ,
1053+ } from '../index' ;
1054+
1055+ describe ( 'coerceToSafeValue' , ( ) => {
1056+ it ( 'should pass through primitives unchanged' , ( ) => {
1057+ expect ( coerceToSafeValue ( 'hello' ) ) . toBe ( 'hello' ) ;
1058+ expect ( coerceToSafeValue ( 42 ) ) . toBe ( 42 ) ;
1059+ expect ( coerceToSafeValue ( true ) ) . toBe ( true ) ;
1060+ expect ( coerceToSafeValue ( null ) ) . toBe ( null ) ;
1061+ expect ( coerceToSafeValue ( undefined ) ) . toBe ( undefined ) ;
1062+ } ) ;
1063+
1064+ it ( 'should extract number from MongoDB $numberDecimal' , ( ) => {
1065+ expect ( coerceToSafeValue ( { $numberDecimal : '250000' } ) ) . toBe ( 250000 ) ;
1066+ } ) ;
1067+
1068+ it ( 'should extract string from MongoDB $oid' , ( ) => {
1069+ expect ( coerceToSafeValue ( { $oid : 'abc123' } ) ) . toBe ( 'abc123' ) ;
1070+ } ) ;
1071+
1072+ it ( 'should extract string from MongoDB $date' , ( ) => {
1073+ expect ( coerceToSafeValue ( { $date : '2024-01-01T00:00:00Z' } ) ) . toBe ( '2024-01-01T00:00:00Z' ) ;
1074+ } ) ;
1075+
1076+ it ( 'should extract name from expanded reference object' , ( ) => {
1077+ expect ( coerceToSafeValue ( { _id : 'x' , name : 'Acme Corp' } ) ) . toBe ( 'Acme Corp' ) ;
1078+ } ) ;
1079+
1080+ it ( 'should extract label when name is not present' , ( ) => {
1081+ expect ( coerceToSafeValue ( { _id : 'x' , label : 'Active' } ) ) . toBe ( 'Active' ) ;
1082+ } ) ;
1083+
1084+ it ( 'should fall back to _id when no name/label' , ( ) => {
1085+ expect ( coerceToSafeValue ( { _id : 'abc123' } ) ) . toBe ( 'abc123' ) ;
1086+ } ) ;
1087+
1088+ it ( 'should handle arrays of primitives' , ( ) => {
1089+ expect ( coerceToSafeValue ( [ 'a' , 'b' , 'c' ] ) ) . toBe ( 'a, b, c' ) ;
1090+ } ) ;
1091+
1092+ it ( 'should handle arrays of objects' , ( ) => {
1093+ expect ( coerceToSafeValue ( [ { name : 'Alice' } , { name : 'Bob' } ] ) ) . toBe ( 'Alice, Bob' ) ;
1094+ } ) ;
1095+
1096+ it ( 'should convert Date to ISO string' , ( ) => {
1097+ const d = new Date ( '2024-06-15T12:00:00Z' ) ;
1098+ expect ( coerceToSafeValue ( d ) ) . toBe ( '2024-06-15T12:00:00.000Z' ) ;
1099+ } ) ;
1100+ } ) ;
1101+
1102+ describe ( 'NumberCellRenderer object safety' , ( ) => {
1103+ it ( 'should handle MongoDB $numberDecimal without crashing' , ( ) => {
1104+ const { container } = render (
1105+ < NumberCellRenderer
1106+ value = { { $numberDecimal : '250000' } }
1107+ field = { { name : 'amount' , type : 'number' } as any }
1108+ />
1109+ ) ;
1110+ expect ( container . innerHTML ) . not . toBe ( '' ) ;
1111+ expect ( screen . getByText ( '250,000' ) ) . toBeInTheDocument ( ) ;
1112+ } ) ;
1113+
1114+ it ( 'should handle expanded reference object without crashing' , ( ) => {
1115+ const { container } = render (
1116+ < NumberCellRenderer
1117+ value = { { _id : 'abc' , name : 'Not a number' } }
1118+ field = { { name : 'amount' , type : 'number' } as any }
1119+ />
1120+ ) ;
1121+ expect ( container . innerHTML ) . not . toBe ( '' ) ;
1122+ // Should render the extracted name string, not crash
1123+ expect ( screen . getByText ( 'Not a number' ) ) . toBeInTheDocument ( ) ;
1124+ } ) ;
1125+ } ) ;
1126+
1127+ describe ( 'CurrencyCellRenderer object safety' , ( ) => {
1128+ it ( 'should handle MongoDB $numberDecimal' , ( ) => {
1129+ const { container } = render (
1130+ < CurrencyCellRenderer
1131+ value = { { $numberDecimal : '5000' } }
1132+ field = { { name : 'price' , type : 'currency' , currency : 'USD' } as any }
1133+ />
1134+ ) ;
1135+ expect ( container . innerHTML ) . not . toBe ( '' ) ;
1136+ expect ( screen . getByText ( / 5 , 0 0 0 / ) ) . toBeInTheDocument ( ) ;
1137+ } ) ;
1138+ } ) ;
1139+
1140+ describe ( 'TextCellRenderer object safety' , ( ) => {
1141+ it ( 'should extract name from object instead of [object Object]' , ( ) => {
1142+ render (
1143+ < TextCellRenderer
1144+ value = { { _id : 'abc' , name : 'Acme Corp' } }
1145+ field = { { name : 'company' , type : 'text' } as any }
1146+ />
1147+ ) ;
1148+ expect ( screen . getByText ( 'Acme Corp' ) ) . toBeInTheDocument ( ) ;
1149+ } ) ;
1150+
1151+ it ( 'should handle arrays of objects' , ( ) => {
1152+ render (
1153+ < TextCellRenderer
1154+ value = { [ { name : 'Alice' } , { name : 'Bob' } ] }
1155+ field = { { name : 'contacts' , type : 'text' } as any }
1156+ />
1157+ ) ;
1158+ expect ( screen . getByText ( 'Alice, Bob' ) ) . toBeInTheDocument ( ) ;
1159+ } ) ;
1160+ } ) ;
1161+
1162+ describe ( 'FormulaCellRenderer object safety' , ( ) => {
1163+ it ( 'should extract value from MongoDB $numberDecimal' , ( ) => {
1164+ render (
1165+ < FormulaCellRenderer
1166+ value = { { $numberDecimal : '42.5' } }
1167+ field = { { name : 'calc' , type : 'formula' } as any }
1168+ />
1169+ ) ;
1170+ expect ( screen . getByText ( '42.5' ) ) . toBeInTheDocument ( ) ;
1171+ } ) ;
1172+ } ) ;
0 commit comments