@@ -126,45 +126,242 @@ describe("DataRow", () => {
126126 const X = true ;
127127 const _ = false ;
128128
129- it ( "should select multiple rows at once" , async ( ) => {
130- // 0 1 2 3 4 5 6 7 8 9
131- createRows ( [ _ , _ , _ , X , _ , _ , _ , _ , _ , _ ] ) ;
132- await shiftToggleRow ( 7 ) ;
133- expectRows ( [ _ , _ , _ , X , X , X , X , X , _ , _ ] ) ;
134- } ) ;
129+ describe ( "selection" , ( ) => {
130+ it ( "should select multiple rows at once" , async ( ) => {
131+ // 0 1 2 3 4 5 6 7 8 9
132+ createRows ( [ _ , _ , _ , X , _ , _ , _ , _ , _ , _ ] ) ;
133+ await shiftToggleRow ( 7 ) ;
134+ expectRows ( [ _ , _ , _ , X , X , X , X , X , _ , _ ] ) ;
135+ } ) ;
135136
136- it ( "should unselect multiple rows" , async ( ) => {
137- // 0 1 2 3 4 5 6 7 8 9
138- createRows ( [ _ , _ , _ , X , X , X , X , X , _ , _ ] ) ;
139- await shiftToggleRow ( 4 ) ;
140- expectRows ( [ _ , _ , _ , X , _ , _ , _ , _ , _ , _ ] ) ;
141- } ) ;
137+ it ( "should unselect multiple rows" , async ( ) => {
138+ // 0 1 2 3 4 5 6 7 8 9
139+ createRows ( [ _ , _ , _ , X , X , X , X , X , _ , _ ] ) ;
140+ await shiftToggleRow ( 4 ) ;
141+ expectRows ( [ _ , _ , _ , X , _ , _ , _ , _ , _ , _ ] ) ;
142+ } ) ;
142143
143- it ( "should select from the start when nothing is selected" , async ( ) => {
144- // 0 1 2 3 4 5 6 7 8 9
145- createRows ( [ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ ] ) ;
146- await shiftToggleRow ( 4 ) ;
147- expectRows ( [ X , X , X , X , X , _ , _ , _ , _ , _ ] ) ;
148- } ) ;
144+ it ( "should select from the start when nothing is selected" , async ( ) => {
145+ // 0 1 2 3 4 5 6 7 8 9
146+ createRows ( [ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ ] ) ;
147+ await shiftToggleRow ( 4 ) ;
148+ expectRows ( [ X , X , X , X , X , _ , _ , _ , _ , _ ] ) ;
149+ } ) ;
149150
150- it ( "should select from the group above when it exists" , async ( ) => {
151- // 0 1 2 3 4 5 6 7 8 9
152- createRows ( [ X , X , _ , _ , _ , _ , X , X , X , _ ] ) ;
153- await shiftToggleRow ( 4 ) ;
154- expectRows ( [ X , X , X , X , X , _ , X , X , X , _ ] ) ;
155- } ) ;
151+ it ( "should select from the group above when it exists" , async ( ) => {
152+ // 0 1 2 3 4 5 6 7 8 9
153+ createRows ( [ X , X , _ , _ , _ , _ , X , X , X , _ ] ) ;
154+ await shiftToggleRow ( 4 ) ;
155+ expectRows ( [ X , X , X , X , X , _ , X , X , X , _ ] ) ;
156+ } ) ;
156157
157- it ( "should select from the group below when no group exists above" , async ( ) => {
158- // 0 1 2 3 4 5 6 7 8 9
159- createRows ( [ _ , _ , _ , _ , _ , _ , X , X , X , _ ] ) ;
160- await shiftToggleRow ( 4 ) ;
161- expectRows ( [ _ , _ , _ , _ , X , X , X , X , X , _ ] ) ;
158+ it ( "should select from the group below when no group exists above" , async ( ) => {
159+ // 0 1 2 3 4 5 6 7 8 9
160+ createRows ( [ _ , _ , _ , _ , _ , _ , X , X , X , _ ] ) ;
161+ await shiftToggleRow ( 4 ) ;
162+ expectRows ( [ _ , _ , _ , _ , X , X , X , X , X , _ ] ) ;
163+ } ) ;
164+
165+ it ( "should batch deselect correctly when multiple groups exist" , async ( ) => {
166+ // 0 1 2 3 4 5 6 7 8 9
167+ createRows ( [ X , X , _ , X , X , X , _ , X , X , _ ] ) ;
168+ await shiftToggleRow ( 4 ) ;
169+ expectRows ( [ X , X , _ , X , _ , _ , _ , X , X , _ ] ) ;
170+ } ) ;
162171 } ) ;
163172
164- it ( "should batch deselect correctly when multiple groups exist" , async ( ) => {
165- // 0 1 2 3 4 5 6 7 8 9
166- createRows ( [ X , X , _ , X , X , X , _ , X , X , _ ] ) ;
167- await shiftToggleRow ( 4 ) ;
168- expectRows ( [ X , X , _ , X , _ , _ , _ , X , X , _ ] ) ;
173+ describe ( "hidden _id column" , ( ) => {
174+ // Helper component to wrap hooks properly
175+ function TestRowWithHiddenId ( {
176+ data,
177+ fields,
178+ patchDocument,
179+ onOpenContextMenu,
180+ isRowSelected,
181+ toggleIsRowSelected,
182+ } : {
183+ data : GenericDocument [ ] ;
184+ fields : string [ ] ;
185+ patchDocument : any ;
186+ onOpenContextMenu : any ;
187+ isRowSelected : ( id : string ) => boolean ;
188+ toggleIsRowSelected : ( id : string ) => void ;
189+ } ) {
190+ // Only include specified fields in columns, potentially hiding _id
191+ const columns = useDataColumns ( {
192+ tableName : "test" ,
193+ localStorageKey : "_disabled_" ,
194+ fields,
195+ data,
196+ } ) ;
197+
198+ const { rows, prepareRow } = useTable (
199+ { columns, data } ,
200+ useResizeColumns ,
201+ ) ;
202+
203+ const connectedDeployment = useMemo (
204+ ( ) => ( { deployment, isDisconnected : false } ) ,
205+ [ ] ,
206+ ) ;
207+
208+ return (
209+ < ConnectedDeploymentContext . Provider value = { connectedDeployment } >
210+ < DataRow
211+ index = { 0 }
212+ style = { { } }
213+ data = { {
214+ areEditsAuthorized : true ,
215+ isRowSelected,
216+ isSelectionAllNonExhaustive : false ,
217+ resizingColumn : undefined ,
218+ onAuthorizeEdits : ( ) => { } ,
219+ patchDocument,
220+ prepareRow,
221+ rows,
222+ tableName : "test" ,
223+ toggleIsRowSelected,
224+ onOpenContextMenu,
225+ onCloseContextMenu : ( ) => { } ,
226+ contextMenuColumn : null ,
227+ contextMenuRow : null ,
228+ canManageTable : true ,
229+ activeSchema : null ,
230+ onEditDocument : ( ) => { } ,
231+ } }
232+ />
233+ </ ConnectedDeploymentContext . Provider >
234+ ) ;
235+ }
236+
237+ it ( "should access _id from row.original when _id column is hidden" , ( ) => {
238+ const patchDocument = jest . fn ( ) ;
239+ const onOpenContextMenu = jest . fn ( ) ;
240+
241+ const data : GenericDocument [ ] = [
242+ { _id : "test-id-1" , name : "John" , age : 30 } ,
243+ { _id : "test-id-2" , name : "Jane" , age : 25 } ,
244+ ] ;
245+
246+ const { container } = render (
247+ < DeploymentInfoContext . Provider value = { mockDeploymentInfo } >
248+ < ConvexProvider client = { mockClient } >
249+ < TestRowWithHiddenId
250+ data = { data }
251+ fields = { [ "name" , "age" ] }
252+ patchDocument = { patchDocument }
253+ onOpenContextMenu = { onOpenContextMenu }
254+ isRowSelected = { ( ) => false }
255+ toggleIsRowSelected = { ( ) => { } }
256+ />
257+ </ ConvexProvider >
258+ </ DeploymentInfoContext . Provider > ,
259+ ) ;
260+
261+ // Verify the row renders without errors
262+ expect ( container . querySelector ( ".DataRow" ) ) . toBeInTheDocument ( ) ;
263+
264+ // Verify that we can see the name and age values
265+ expect ( container ) . toHaveTextContent ( "John" ) ;
266+ expect ( container ) . toHaveTextContent ( "30" ) ;
267+ } ) ;
268+
269+ it ( "should correctly identify rows by _id when _id column is hidden" , ( ) => {
270+ const isRowSelected = jest . fn ( ( ) => false ) ;
271+ const toggleIsRowSelected = jest . fn ( ) ;
272+
273+ const data : GenericDocument [ ] = [
274+ { _id : "test-id-1" , name : "John" , age : 30 } ,
275+ { _id : "test-id-2" , name : "Jane" , age : 25 } ,
276+ ] ;
277+
278+ render (
279+ < DeploymentInfoContext . Provider value = { mockDeploymentInfo } >
280+ < ConvexProvider client = { mockClient } >
281+ < TestRowWithHiddenId
282+ data = { data }
283+ fields = { [ "name" , "age" ] }
284+ patchDocument = { async ( ) => undefined }
285+ onOpenContextMenu = { ( ) => { } }
286+ isRowSelected = { isRowSelected }
287+ toggleIsRowSelected = { toggleIsRowSelected }
288+ />
289+ </ ConvexProvider >
290+ </ DeploymentInfoContext . Provider > ,
291+ ) ;
292+
293+ // Verify isRowSelected was called with the correct _id
294+ expect ( isRowSelected ) . toHaveBeenCalledWith ( "test-id-1" ) ;
295+ } ) ;
296+
297+ it ( "should open context menu with correct _id when _id column is hidden" , async ( ) => {
298+ const onOpenContextMenu = jest . fn ( ) ;
299+
300+ const data : GenericDocument [ ] = [
301+ { _id : "test-id-1" , name : "John" , age : 30 } ,
302+ ] ;
303+
304+ const { container } = render (
305+ < DeploymentInfoContext . Provider value = { mockDeploymentInfo } >
306+ < ConvexProvider client = { mockClient } >
307+ < TestRowWithHiddenId
308+ data = { data }
309+ fields = { [ "name" , "age" ] }
310+ patchDocument = { async ( ) => undefined }
311+ onOpenContextMenu = { onOpenContextMenu }
312+ isRowSelected = { ( ) => false }
313+ toggleIsRowSelected = { ( ) => { } }
314+ />
315+ </ ConvexProvider >
316+ </ DeploymentInfoContext . Provider > ,
317+ ) ;
318+
319+ // Find and right-click the checkbox
320+ const checkbox = container . querySelector ( 'input[type="checkbox"]' ) ;
321+ expect ( checkbox ) . toBeInTheDocument ( ) ;
322+
323+ const user = userEvent . setup ( ) ;
324+ await user . pointer ( {
325+ target : checkbox ! . parentElement ! ,
326+ keys : "[MouseRight]" ,
327+ } ) ;
328+
329+ // Verify onOpenContextMenu was called with correct _id
330+ expect ( onOpenContextMenu ) . toHaveBeenCalledWith (
331+ expect . any ( Object ) ,
332+ "test-id-1" ,
333+ null ,
334+ ) ;
335+ } ) ;
336+
337+ it ( "should handle recently created row highlighting when _id column is hidden" , ( ) => {
338+ const data : GenericDocument [ ] = [
339+ {
340+ _id : "test-id-1" ,
341+ _creationTime : Date . now ( ) - 500 , // Created 500ms ago
342+ name : "John" ,
343+ age : 30 ,
344+ } ,
345+ ] ;
346+
347+ const { container } = render (
348+ < DeploymentInfoContext . Provider value = { mockDeploymentInfo } >
349+ < ConvexProvider client = { mockClient } >
350+ < TestRowWithHiddenId
351+ data = { data }
352+ fields = { [ "name" , "age" ] }
353+ patchDocument = { async ( ) => undefined }
354+ onOpenContextMenu = { ( ) => { } }
355+ isRowSelected = { ( ) => false }
356+ toggleIsRowSelected = { ( ) => { } }
357+ />
358+ </ ConvexProvider >
359+ </ DeploymentInfoContext . Provider > ,
360+ ) ;
361+
362+ // Verify the row renders with the highlight animation
363+ const row = container . querySelector ( ".DataRow" ) ;
364+ expect ( row ) . toHaveClass ( "animate-highlight" ) ;
365+ } ) ;
169366 } ) ;
170367} ) ;
0 commit comments