bito-code-review[bot] commented on code in PR #38397:
URL: https://github.com/apache/superset/pull/38397#discussion_r2884329782


##########
superset-frontend/packages/superset-ui-core/src/components/Table/utils/InteractiveTableUtils.test.ts:
##########
@@ -0,0 +1,526 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { SUPERSET_TABLE_COLUMN } from '..';
+import InteractiveTableUtils from './InteractiveTableUtils';
+
+const mockColumns = [
+  { key: 'name', dataIndex: 'name', title: 'Name' },
+  { key: 'age', dataIndex: 'age', title: 'Age' },
+];
+
+const createMockTable = (numCols = 2): HTMLTableElement => {
+  const table = document.createElement('table');
+  const thead = document.createElement('thead');
+  const tr = document.createElement('tr');
+  for (let i = 0; i < numCols; i += 1) {
+    const th = document.createElement('th');
+    tr.appendChild(th);
+  }
+  thead.appendChild(tr);
+  table.appendChild(thead);
+  document.body.appendChild(table);
+  return table;
+};
+
+afterEach(() => {
+  document.body.innerHTML = '';
+});
+
+test('constructor initializes with correct defaults', () => {
+  const table = createMockTable();
+  const setDerivedColumns = jest.fn();
+  const utils = new InteractiveTableUtils(table, mockColumns, 
setDerivedColumns);
+
+  expect(utils.tableRef).toBe(table);
+  expect(utils.isDragging).toBe(false);
+  expect(utils.resizable).toBe(false);
+  expect(utils.reorderable).toBe(false);
+  expect(utils.derivedColumns).toEqual(mockColumns);
+  expect(utils.RESIZE_INDICATOR_THRESHOLD).toBe(8);
+});
+
+test('setTableRef updates tableRef', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(
+    table,
+    mockColumns,
+    jest.fn(),
+  );
+  const newTable = createMockTable();
+  utils.setTableRef(newTable);
+  expect(utils.tableRef).toBe(newTable);
+});
+
+test('getColumnIndex returns -1 when columnRef has no parent', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.columnRef = null;
+  expect(utils.getColumnIndex()).toBe(-1);
+});
+
+test('getColumnIndex returns correct index when columnRef is in a row', () => {
+  const table = createMockTable(3);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const row = table.rows[0];
+  utils.columnRef = row.cells[1] as unknown as typeof utils.columnRef;
+  expect(utils.getColumnIndex()).toBe(1);
+});
+
+test('allowDrop calls preventDefault on the event', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const event = { preventDefault: jest.fn() } as unknown as DragEvent;
+  utils.allowDrop(event);
+  expect(event.preventDefault).toHaveBeenCalledTimes(1);
+});
+
+test('handleMouseup clears mouseDown and resets dragging state', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const th = document.createElement('th') as unknown as typeof utils.columnRef;
+  utils.columnRef = th;
+  (th as any).mouseDown = true;
+  utils.isDragging = true;
+
+  utils.handleMouseup();
+
+  expect((th as any).mouseDown).toBe(false);
+  expect(utils.isDragging).toBe(false);
+});
+
+test('handleMouseup works when columnRef is null', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.columnRef = null;
+  utils.isDragging = true;
+
+  utils.handleMouseup();
+
+  expect(utils.isDragging).toBe(false);
+});
+
+test('handleMouseDown sets mouseDown and oldX when within resize range', () => 
{
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const target = document.createElement('th') as any;
+  Object.defineProperty(target, 'offsetWidth', { value: 100, configurable: 
true });
+
+  const event = {
+    currentTarget: target,
+    offsetX: 95, // 100 - 95 = 5, within threshold of 8
+    x: 95,
+  } as unknown as MouseEvent;
+
+  utils.handleMouseDown(event);
+
+  expect(target.mouseDown).toBe(true);
+  expect(target.oldX).toBe(95);
+  expect(target.oldWidth).toBe(100);
+  expect(target.draggable).toBe(false);
+});
+
+test('handleMouseDown sets draggable when outside resize range and 
reorderable', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.reorderable = true;
+
+  const target = document.createElement('th') as any;
+  Object.defineProperty(target, 'offsetWidth', { value: 100, configurable: 
true });
+
+  const event = {
+    currentTarget: target,
+    offsetX: 50, // 100 - 50 = 50, outside threshold of 8
+    x: 50,
+  } as unknown as MouseEvent;
+
+  utils.handleMouseDown(event);
+
+  expect(target.draggable).toBe(true);
+});
+
+test('initializeResizableColumns adds event listeners when resizable is true', 
() => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const addEventSpy = jest.spyOn(cell, 'addEventListener');
+
+  utils.initializeResizableColumns(true, table);
+
+  expect(utils.resizable).toBe(true);
+  expect(addEventSpy).toHaveBeenCalledWith('mousedown', utils.handleMouseDown);
+  expect(addEventSpy).toHaveBeenCalledWith(
+    'mousemove',
+    utils.handleMouseMove,
+    true,
+  );
+});
+
+test('initializeResizableColumns removes event listeners when resizable is 
false', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const removeEventSpy = jest.spyOn(cell, 'removeEventListener');
+
+  utils.initializeResizableColumns(false, table);
+
+  expect(utils.resizable).toBe(false);
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'mousedown',
+    utils.handleMouseDown,
+  );
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'mousemove',
+    utils.handleMouseMove,
+    true,
+  );
+});
+
+test('initializeDragDropColumns adds event listeners when reorderable is 
true', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const addEventSpy = jest.spyOn(cell, 'addEventListener');
+
+  utils.initializeDragDropColumns(true, table);
+
+  expect(utils.reorderable).toBe(true);
+  expect(addEventSpy).toHaveBeenCalledWith(
+    'dragstart',
+    utils.handleColumnDragStart,
+  );
+  expect(addEventSpy).toHaveBeenCalledWith('drop', utils.handleDragDrop);
+});
+
+test('initializeDragDropColumns removes event listeners when reorderable is 
false', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const removeEventSpy = jest.spyOn(cell, 'removeEventListener');
+
+  utils.initializeDragDropColumns(false, table);
+
+  expect(utils.reorderable).toBe(false);
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'dragstart',
+    utils.handleColumnDragStart,
+  );
+  expect(removeEventSpy).toHaveBeenCalledWith('drop', utils.handleDragDrop);
+});

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Missing Event Listener Removal Assertions</b></div>
   <div id="fix">
   
   The test verifies removal of 'dragstart' and 'drop' listeners but omits 
'mousedown' and 'dragover', which are also removed. Include checks for all 
removals.
   </div>
   
   
   <details>
   <summary>
   <b>Code suggestion</b>
   </summary>
   <blockquote>Check the AI-generated fix before applying</blockquote>
   <div id="code">
   
   
   ````suggestion
     expect(removeEventSpy).toHaveBeenCalledWith('drop', utils.handleDragDrop);
     expect(removeEventSpy).toHaveBeenCalledWith('mousedown', 
utils.handleMouseDown);
     expect(removeEventSpy).toHaveBeenCalledWith('dragover', utils.allowDrop);
   });
   ````
   
   </div>
   </details>
   
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d90d95</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/packages/superset-ui-core/src/components/Table/utils/InteractiveTableUtils.test.ts:
##########
@@ -0,0 +1,526 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { SUPERSET_TABLE_COLUMN } from '..';
+import InteractiveTableUtils from './InteractiveTableUtils';
+
+const mockColumns = [
+  { key: 'name', dataIndex: 'name', title: 'Name' },
+  { key: 'age', dataIndex: 'age', title: 'Age' },
+];
+
+const createMockTable = (numCols = 2): HTMLTableElement => {
+  const table = document.createElement('table');
+  const thead = document.createElement('thead');
+  const tr = document.createElement('tr');
+  for (let i = 0; i < numCols; i += 1) {
+    const th = document.createElement('th');
+    tr.appendChild(th);
+  }
+  thead.appendChild(tr);
+  table.appendChild(thead);
+  document.body.appendChild(table);
+  return table;
+};
+
+afterEach(() => {
+  document.body.innerHTML = '';
+});
+
+test('constructor initializes with correct defaults', () => {
+  const table = createMockTable();
+  const setDerivedColumns = jest.fn();
+  const utils = new InteractiveTableUtils(table, mockColumns, 
setDerivedColumns);
+
+  expect(utils.tableRef).toBe(table);
+  expect(utils.isDragging).toBe(false);
+  expect(utils.resizable).toBe(false);
+  expect(utils.reorderable).toBe(false);
+  expect(utils.derivedColumns).toEqual(mockColumns);
+  expect(utils.RESIZE_INDICATOR_THRESHOLD).toBe(8);
+});
+
+test('setTableRef updates tableRef', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(
+    table,
+    mockColumns,
+    jest.fn(),
+  );
+  const newTable = createMockTable();
+  utils.setTableRef(newTable);
+  expect(utils.tableRef).toBe(newTable);
+});
+
+test('getColumnIndex returns -1 when columnRef has no parent', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.columnRef = null;
+  expect(utils.getColumnIndex()).toBe(-1);
+});
+
+test('getColumnIndex returns correct index when columnRef is in a row', () => {
+  const table = createMockTable(3);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const row = table.rows[0];
+  utils.columnRef = row.cells[1] as unknown as typeof utils.columnRef;
+  expect(utils.getColumnIndex()).toBe(1);
+});
+
+test('allowDrop calls preventDefault on the event', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const event = { preventDefault: jest.fn() } as unknown as DragEvent;
+  utils.allowDrop(event);
+  expect(event.preventDefault).toHaveBeenCalledTimes(1);
+});
+
+test('handleMouseup clears mouseDown and resets dragging state', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const th = document.createElement('th') as unknown as typeof utils.columnRef;
+  utils.columnRef = th;
+  (th as any).mouseDown = true;
+  utils.isDragging = true;
+
+  utils.handleMouseup();
+
+  expect((th as any).mouseDown).toBe(false);
+  expect(utils.isDragging).toBe(false);
+});
+
+test('handleMouseup works when columnRef is null', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.columnRef = null;
+  utils.isDragging = true;
+
+  utils.handleMouseup();
+
+  expect(utils.isDragging).toBe(false);
+});
+
+test('handleMouseDown sets mouseDown and oldX when within resize range', () => 
{
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const target = document.createElement('th') as any;
+  Object.defineProperty(target, 'offsetWidth', { value: 100, configurable: 
true });
+
+  const event = {
+    currentTarget: target,
+    offsetX: 95, // 100 - 95 = 5, within threshold of 8
+    x: 95,
+  } as unknown as MouseEvent;
+
+  utils.handleMouseDown(event);
+
+  expect(target.mouseDown).toBe(true);
+  expect(target.oldX).toBe(95);
+  expect(target.oldWidth).toBe(100);
+  expect(target.draggable).toBe(false);
+});
+
+test('handleMouseDown sets draggable when outside resize range and 
reorderable', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.reorderable = true;
+
+  const target = document.createElement('th') as any;
+  Object.defineProperty(target, 'offsetWidth', { value: 100, configurable: 
true });
+
+  const event = {
+    currentTarget: target,
+    offsetX: 50, // 100 - 50 = 50, outside threshold of 8
+    x: 50,
+  } as unknown as MouseEvent;
+
+  utils.handleMouseDown(event);
+
+  expect(target.draggable).toBe(true);
+});
+
+test('initializeResizableColumns adds event listeners when resizable is true', 
() => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const addEventSpy = jest.spyOn(cell, 'addEventListener');
+
+  utils.initializeResizableColumns(true, table);
+
+  expect(utils.resizable).toBe(true);
+  expect(addEventSpy).toHaveBeenCalledWith('mousedown', utils.handleMouseDown);
+  expect(addEventSpy).toHaveBeenCalledWith(
+    'mousemove',
+    utils.handleMouseMove,
+    true,
+  );
+});
+
+test('initializeResizableColumns removes event listeners when resizable is 
false', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const removeEventSpy = jest.spyOn(cell, 'removeEventListener');
+
+  utils.initializeResizableColumns(false, table);
+
+  expect(utils.resizable).toBe(false);
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'mousedown',
+    utils.handleMouseDown,
+  );
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'mousemove',
+    utils.handleMouseMove,
+    true,
+  );
+});
+
+test('initializeDragDropColumns adds event listeners when reorderable is 
true', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const addEventSpy = jest.spyOn(cell, 'addEventListener');
+
+  utils.initializeDragDropColumns(true, table);
+
+  expect(utils.reorderable).toBe(true);
+  expect(addEventSpy).toHaveBeenCalledWith(
+    'dragstart',
+    utils.handleColumnDragStart,
+  );
+  expect(addEventSpy).toHaveBeenCalledWith('drop', utils.handleDragDrop);
+});

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Missing Event Listener Assertions</b></div>
   <div id="fix">
   
   The test verifies 'dragstart' and 'drop' listeners but omits 'mousedown' and 
'dragover', which are also added. Include checks for all listeners to ensure 
complete coverage.
   </div>
   
   
   <details>
   <summary>
   <b>Code suggestion</b>
   </summary>
   <blockquote>Check the AI-generated fix before applying</blockquote>
   <div id="code">
   
   
   ````suggestion
     expect(addEventSpy).toHaveBeenCalledWith('drop', utils.handleDragDrop);
     expect(addEventSpy).toHaveBeenCalledWith('mousedown', 
utils.handleMouseDown);
     expect(addEventSpy).toHaveBeenCalledWith('dragover', utils.allowDrop);
   });
   ````
   
   </div>
   </details>
   
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d90d95</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/packages/superset-ui-core/test/connection/SupersetClientClass.test.ts:
##########
@@ -108,6 +108,20 @@ describe('SupersetClientClass', () => {
       expect(fetchMock.callHistory.calls(LOGIN_GLOB)).toHaveLength(0);
     });
 
+    test('getCSRFToken() returns existing csrfToken without fetching when 
already set', async () => {
+      const client = new SupersetClientClass({ csrfToken: 'existing_token' });
+      const token = await client.getCSRFToken();
+      expect(token).toBe('existing_token');
+      expect(fetchMock.callHistory.calls(LOGIN_GLOB)).toHaveLength(0);
+    });
+
+    test('getCSRFToken() calls fetchCSRFToken when csrfToken is not set (line 
261 || branch)', async () => {
+      const client = new SupersetClientClass({});
+      const token = await client.getCSRFToken();
+      expect(fetchMock.callHistory.calls(LOGIN_GLOB)).toHaveLength(1);
+      expect(token).toBe(1234);

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Test expectation type mismatch</b></div>
   <div id="fix">
   
   The test expects the CSRF token to be the number 1234, but getCSRFToken() 
returns a string because the code does `json.result as string`. This type 
mismatch will cause the test to fail at runtime.
   </div>
   
   
   <details>
   <summary>
   <b>Code suggestion</b>
   </summary>
   <blockquote>Check the AI-generated fix before applying</blockquote>
   <div id="code">
   
   
   ````suggestion
         expect(token).toBe("1234");
   ````
   
   </div>
   </details>
   
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d90d95</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



##########
superset-frontend/packages/superset-ui-core/src/components/Table/utils/InteractiveTableUtils.test.ts:
##########
@@ -0,0 +1,526 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { SUPERSET_TABLE_COLUMN } from '..';
+import InteractiveTableUtils from './InteractiveTableUtils';
+
+const mockColumns = [
+  { key: 'name', dataIndex: 'name', title: 'Name' },
+  { key: 'age', dataIndex: 'age', title: 'Age' },
+];
+
+const createMockTable = (numCols = 2): HTMLTableElement => {
+  const table = document.createElement('table');
+  const thead = document.createElement('thead');
+  const tr = document.createElement('tr');
+  for (let i = 0; i < numCols; i += 1) {
+    const th = document.createElement('th');
+    tr.appendChild(th);
+  }
+  thead.appendChild(tr);
+  table.appendChild(thead);
+  document.body.appendChild(table);
+  return table;
+};
+
+afterEach(() => {
+  document.body.innerHTML = '';
+});
+
+test('constructor initializes with correct defaults', () => {
+  const table = createMockTable();
+  const setDerivedColumns = jest.fn();
+  const utils = new InteractiveTableUtils(table, mockColumns, 
setDerivedColumns);
+
+  expect(utils.tableRef).toBe(table);
+  expect(utils.isDragging).toBe(false);
+  expect(utils.resizable).toBe(false);
+  expect(utils.reorderable).toBe(false);
+  expect(utils.derivedColumns).toEqual(mockColumns);
+  expect(utils.RESIZE_INDICATOR_THRESHOLD).toBe(8);
+});
+
+test('setTableRef updates tableRef', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(
+    table,
+    mockColumns,
+    jest.fn(),
+  );
+  const newTable = createMockTable();
+  utils.setTableRef(newTable);
+  expect(utils.tableRef).toBe(newTable);
+});
+
+test('getColumnIndex returns -1 when columnRef has no parent', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.columnRef = null;
+  expect(utils.getColumnIndex()).toBe(-1);
+});
+
+test('getColumnIndex returns correct index when columnRef is in a row', () => {
+  const table = createMockTable(3);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const row = table.rows[0];
+  utils.columnRef = row.cells[1] as unknown as typeof utils.columnRef;
+  expect(utils.getColumnIndex()).toBe(1);
+});
+
+test('allowDrop calls preventDefault on the event', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const event = { preventDefault: jest.fn() } as unknown as DragEvent;
+  utils.allowDrop(event);
+  expect(event.preventDefault).toHaveBeenCalledTimes(1);
+});
+
+test('handleMouseup clears mouseDown and resets dragging state', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const th = document.createElement('th') as unknown as typeof utils.columnRef;
+  utils.columnRef = th;
+  (th as any).mouseDown = true;
+  utils.isDragging = true;
+
+  utils.handleMouseup();
+
+  expect((th as any).mouseDown).toBe(false);
+  expect(utils.isDragging).toBe(false);
+});
+
+test('handleMouseup works when columnRef is null', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.columnRef = null;
+  utils.isDragging = true;
+
+  utils.handleMouseup();
+
+  expect(utils.isDragging).toBe(false);
+});
+
+test('handleMouseDown sets mouseDown and oldX when within resize range', () => 
{
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const target = document.createElement('th') as any;
+  Object.defineProperty(target, 'offsetWidth', { value: 100, configurable: 
true });
+
+  const event = {
+    currentTarget: target,
+    offsetX: 95, // 100 - 95 = 5, within threshold of 8
+    x: 95,
+  } as unknown as MouseEvent;
+
+  utils.handleMouseDown(event);
+
+  expect(target.mouseDown).toBe(true);
+  expect(target.oldX).toBe(95);
+  expect(target.oldWidth).toBe(100);
+  expect(target.draggable).toBe(false);
+});
+
+test('handleMouseDown sets draggable when outside resize range and 
reorderable', () => {
+  const table = createMockTable();
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  utils.reorderable = true;
+
+  const target = document.createElement('th') as any;
+  Object.defineProperty(target, 'offsetWidth', { value: 100, configurable: 
true });
+
+  const event = {
+    currentTarget: target,
+    offsetX: 50, // 100 - 50 = 50, outside threshold of 8
+    x: 50,
+  } as unknown as MouseEvent;
+
+  utils.handleMouseDown(event);
+
+  expect(target.draggable).toBe(true);
+});
+
+test('initializeResizableColumns adds event listeners when resizable is true', 
() => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const addEventSpy = jest.spyOn(cell, 'addEventListener');
+
+  utils.initializeResizableColumns(true, table);
+
+  expect(utils.resizable).toBe(true);
+  expect(addEventSpy).toHaveBeenCalledWith('mousedown', utils.handleMouseDown);
+  expect(addEventSpy).toHaveBeenCalledWith(
+    'mousemove',
+    utils.handleMouseMove,
+    true,
+  );
+});
+
+test('initializeResizableColumns removes event listeners when resizable is 
false', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const removeEventSpy = jest.spyOn(cell, 'removeEventListener');
+
+  utils.initializeResizableColumns(false, table);
+
+  expect(utils.resizable).toBe(false);
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'mousedown',
+    utils.handleMouseDown,
+  );
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'mousemove',
+    utils.handleMouseMove,
+    true,
+  );
+});
+
+test('initializeDragDropColumns adds event listeners when reorderable is 
true', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const addEventSpy = jest.spyOn(cell, 'addEventListener');
+
+  utils.initializeDragDropColumns(true, table);
+
+  expect(utils.reorderable).toBe(true);
+  expect(addEventSpy).toHaveBeenCalledWith(
+    'dragstart',
+    utils.handleColumnDragStart,
+  );
+  expect(addEventSpy).toHaveBeenCalledWith('drop', utils.handleDragDrop);
+});
+
+test('initializeDragDropColumns removes event listeners when reorderable is 
false', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+  const cell = table.rows[0].cells[0];
+  const removeEventSpy = jest.spyOn(cell, 'removeEventListener');
+
+  utils.initializeDragDropColumns(false, table);
+
+  expect(utils.reorderable).toBe(false);
+  expect(removeEventSpy).toHaveBeenCalledWith(
+    'dragstart',
+    utils.handleColumnDragStart,
+  );
+  expect(removeEventSpy).toHaveBeenCalledWith('drop', utils.handleDragDrop);
+});
+
+test('handleColumnDragStart sets isDragging and calls setData', () => {
+  const table = createMockTable(2);
+  const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
+
+  const row = table.rows[0];
+  const target = row.cells[0] as any;
+  const setDataMock = jest.fn();
+  const event = {
+    currentTarget: target,
+    dataTransfer: { setData: setDataMock },
+  } as unknown as DragEvent;
+
+  utils.handleColumnDragStart(event);
+
+  expect(utils.isDragging).toBe(true);
+  expect(setDataMock).toHaveBeenCalledWith(
+    SUPERSET_TABLE_COLUMN,
+    expect.any(String),
+  );
+});
+
+test('handleDragDrop reorders columns when valid drag data exists', () => {
+  const table = createMockTable(2);
+  const setDerivedColumns = jest.fn();
+  const utils = new InteractiveTableUtils(table, mockColumns, 
setDerivedColumns);
+
+  const row = table.rows[0];
+  // Set columnRef to first column (drag source)
+  utils.columnRef = row.cells[0] as unknown as typeof utils.columnRef;
+
+  const dragData = JSON.stringify({ index: 0, columnData: mockColumns[0] });
+  const dropTarget = row.cells[1];
+  const event = {
+    currentTarget: dropTarget,
+    dataTransfer: { getData: jest.fn().mockReturnValue(dragData) },
+    preventDefault: jest.fn(),
+  } as unknown as DragEvent;
+
+  utils.handleDragDrop(event);
+
+  expect(event.preventDefault).toHaveBeenCalledTimes(1);
+  expect(setDerivedColumns).toHaveBeenCalledTimes(1);
+});

Review Comment:
   <div>
   
   
   <div id="suggestion">
   <div id="issue"><b>Incomplete Behavior Assertion</b></div>
   <div id="fix">
   
   The test checks that setDerivedColumns is called but does not assert the 
reordered columns, potentially missing bugs in drag-drop reordering logic. Add 
the assertion to validate the behavior directly.
   </div>
   
   
   <details>
   <summary>
   <b>Code suggestion</b>
   </summary>
   <blockquote>Check the AI-generated fix before applying</blockquote>
   <div id="code">
   
   
   ````suggestion
     expect(event.preventDefault).toHaveBeenCalledTimes(1);
     expect(setDerivedColumns).toHaveBeenCalledTimes(1);
     expect(setDerivedColumns).toHaveBeenCalledWith([mockColumns[1], 
mockColumns[0]]);
   });
   ````
   
   </div>
   </details>
   
   
   
   </div>
   
   
   
   
   <small><i>Code Review Run #d90d95</i></small>
   </div>
   
   ---
   Should Bito avoid suggestions like this for future reviews? (<a 
href=https://alpha.bito.ai/home/ai-agents/review-rules>Manage Rules</a>)
   - [ ] Yes, avoid them



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to