Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import type * as LoadSelectedEvent from '../LoadSelectedEvent/LoadSelectedEvent.ts'
import type { ChatDebugViewState } from '../State/ChatDebugViewState.ts'
import * as LoadSelectedEvent from '../LoadSelectedEvent/LoadSelectedEvent.ts'
import { selectEventAtIndex } from '../SelectEventAtIndex/SelectEventAtIndex.ts'

export const handleEventRowClickDependencies = {
loadSelectedEvent: LoadSelectedEvent.loadSelectedEvent,
}
type LoadSelectedEventFn = typeof LoadSelectedEvent.loadSelectedEvent

const isPrimaryButton = (button: number): boolean => {
return button === 0
}

export const handleEventRowClick = async (state: ChatDebugViewState, index: string | number, button: number = 0): Promise<ChatDebugViewState> => {
export const handleEventRowClick = async (
state: ChatDebugViewState,
index: string | number,
button: number = 0,
loadSelectedEvent?: LoadSelectedEventFn,
): Promise<ChatDebugViewState> => {
const actual = typeof index === 'string' ? Number.parseInt(index, 10) : index
if (!isPrimaryButton(button)) {
return state
}
if (actual === -1) {
return state
}
return selectEventAtIndex(state, actual, handleEventRowClickDependencies)
return selectEventAtIndex(state, actual, loadSelectedEvent)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type * as LoadSelectedEvent from '../LoadSelectedEvent/LoadSelectedEvent.ts'
import type { ChatDebugViewState } from '../State/ChatDebugViewState.ts'
import { getTableBodyEventIndex } from '../GetTableBodyEventIndex/GetTableBodyEventIndex.ts'
import { handleEventRowClick } from '../HandleEventRowClick/HandleEventRowClick.ts'

type LoadSelectedEventFn = typeof LoadSelectedEvent.loadSelectedEvent

export const handleEventRowClickAt = async (
state: ChatDebugViewState,
eventX: number,
eventY: number,
button: number = 0,
loadSelectedEvent?: LoadSelectedEventFn,
): Promise<ChatDebugViewState> => {
const selectedEventIndex = getTableBodyEventIndex(state, eventX, eventY)
return handleEventRowClick(state, selectedEventIndex, button)
return handleEventRowClick(state, selectedEventIndex, button, loadSelectedEvent)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,14 @@ import { mergeSelectedEventDetails } from '../MergeSelectedEventDetails/MergeSel
import { withSelectedEventVisible } from '../VirtualTable/VirtualTable.ts'
import { withPreparedSelectedEventPreview } from '../WithPreparedSelectedEventPreview/WithPreparedSelectedEventPreview.ts'

export interface SelectEventAtIndexDependencies {
readonly loadSelectedEvent: typeof LoadSelectedEvent.loadSelectedEvent
}

export const selectEventAtIndexDependencies: SelectEventAtIndexDependencies = {
loadSelectedEvent: LoadSelectedEvent.loadSelectedEvent,
}
type LoadSelectedEventFn = typeof LoadSelectedEvent.loadSelectedEvent

export const getCurrentEvents = (state: ChatDebugViewState): readonly ChatViewEvent[] => getSharedCurrentEvents(state)

export const selectEventAtIndex = async (
state: ChatDebugViewState,
selectedEventIndex: number,
dependencies: SelectEventAtIndexDependencies = selectEventAtIndexDependencies,
loadSelectedEvent: LoadSelectedEventFn = LoadSelectedEvent.loadSelectedEvent,
): Promise<ChatDebugViewState> => {
const { databaseName, dataBaseVersion, detailTabs, eventStoreName, sessionId, sessionIdIndexName } = state
const selectedDetailTab = getSelectedDetailTab(detailTabs)
Expand All @@ -43,7 +37,7 @@ export const selectEventAtIndex = async (
selectedEventIndex,
}
}
const selectedEventDetails = await dependencies.loadSelectedEvent(
const selectedEventDetails = await loadSelectedEvent(
databaseName,
dataBaseVersion,
eventStoreName,
Expand Down
22 changes: 12 additions & 10 deletions packages/chat-debug-view/test/HandleEventRowClickAt.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { afterEach, expect, jest, test } from '@jest/globals'
import type * as LoadSelectedEvent from '../src/parts/LoadSelectedEvent/LoadSelectedEvent.ts'
import type { ChatDebugViewState } from '../src/parts/State/ChatDebugViewState.ts'
import { createDetailTabs } from '../src/parts/CreateDetailTabs/CreateDetailTabs.ts'
import { getSelectedDetailTab } from '../src/parts/GetSelectedDetailTab/GetSelectedDetailTab.ts'
import { handleEventRowClickDependencies } from '../src/parts/HandleEventRowClick/HandleEventRowClick.ts'
import { handleEventRowClickAt } from '../src/parts/HandleEventRowClickAt/HandleEventRowClickAt.ts'
import { hasDetailTab } from '../src/parts/HasDetailTab/HasDetailTab.ts'
import { createDefaultState } from '../src/parts/State/CreateDefaultState.ts'
import { applyVirtualTableState } from '../src/parts/VirtualTable/VirtualTable.ts'

type LoadSelectedEventFn = typeof LoadSelectedEvent.loadSelectedEvent

const tableClientX = 30
const row0ClientY = 180
const row1ClientY = 197
Expand All @@ -30,7 +32,7 @@ afterEach(() => {
})

test('handleEventRowClick should select the clicked event row and load details', async () => {
const loadSelectedEventSpy = jest.spyOn(handleEventRowClickDependencies, 'loadSelectedEvent').mockResolvedValue({
const loadSelectedEvent = jest.fn<LoadSelectedEventFn>().mockResolvedValue({
detail: 'value',
eventId: 3,
type: 'request',
Expand Down Expand Up @@ -61,7 +63,7 @@ test('handleEventRowClick should select the clicked event row and load details',
],
sessionId: 'session-1',
})
const result = await handleEventRowClickAt(state, tableClientX, row2ClientY, 0)
const result = await handleEventRowClickAt(state, tableClientX, row2ClientY, 0, loadSelectedEvent)

expect(result.selectedEventIndex).toBe(2)
expect(result.selectedEvent).toEqual({
Expand All @@ -72,7 +74,7 @@ test('handleEventRowClick should select the clicked event row and load details',
startTime: '2026-03-08T00:00:02.000Z',
type: 'request',
})
expect(loadSelectedEventSpy).toHaveBeenCalledWith('lvce-chat-view-sessions', 2, 'chat-view-events', 'session-1', 'sessionId', 3, 'request')
expect(loadSelectedEvent).toHaveBeenCalledWith('lvce-chat-view-sessions', 2, 'chat-view-events', 'session-1', 'sessionId', 3, 'request')
})

test('handleEventRowClick should ignore clicks outside the table body', async () => {
Expand Down Expand Up @@ -127,7 +129,7 @@ test('handleEventRowClick should fall back to the in-memory event when it has no
})

test('handleEventRowClick should fall back to the selected list event when loading details returns null', async () => {
jest.spyOn(handleEventRowClickDependencies, 'loadSelectedEvent').mockResolvedValue(null)
const loadSelectedEvent = jest.fn<LoadSelectedEventFn>().mockResolvedValue(null)
const state = createClickableState({
events: [
{
Expand All @@ -141,7 +143,7 @@ test('handleEventRowClick should fall back to the selected list event when loadi
sessionId: 'session-1',
})

const result = await handleEventRowClickAt(state, tableClientX, row0ClientY, 0)
const result = await handleEventRowClickAt(state, tableClientX, row0ClientY, 0, loadSelectedEvent)

expect(result.selectedEventIndex).toBe(0)
expect(result.selectedEventId).toBe(1)
Expand All @@ -155,7 +157,7 @@ test('handleEventRowClick should fall back to the selected list event when loadi
})

test('handleEventRowClick should preserve selected detail tab when switching rows', async () => {
jest.spyOn(handleEventRowClickDependencies, 'loadSelectedEvent').mockResolvedValue({
const loadSelectedEvent = jest.fn<LoadSelectedEventFn>().mockResolvedValue({
detail: 'preview',
eventId: 2,
type: 'response',
Expand All @@ -177,7 +179,7 @@ test('handleEventRowClick should preserve selected detail tab when switching row
sessionId: 'session-1',
})

const result = await handleEventRowClickAt(state, tableClientX, row1ClientY, 0)
const result = await handleEventRowClickAt(state, tableClientX, row1ClientY, 0, loadSelectedEvent)

expect(getSelectedDetailTab(result.detailTabs)).toBe('preview')
expect(result.selectedEventIndex).toBe(1)
Expand All @@ -190,7 +192,7 @@ test('handleEventRowClick should preserve selected detail tab when switching row
})

test('handleEventRowClick should fall back to response and hide timing when the selected event has no timing details', async () => {
jest.spyOn(handleEventRowClickDependencies, 'loadSelectedEvent').mockResolvedValue({
const loadSelectedEvent = jest.fn<LoadSelectedEventFn>().mockResolvedValue({
detail: 'preview',
eventId: 2,
type: 'chat-message-added',
Expand All @@ -214,7 +216,7 @@ test('handleEventRowClick should fall back to response and hide timing when the
sessionId: 'session-1',
})

const result = await handleEventRowClickAt(state, tableClientX, row1ClientY, 0)
const result = await handleEventRowClickAt(state, tableClientX, row1ClientY, 0, loadSelectedEvent)

expect(getSelectedDetailTab(result.detailTabs)).toBe('response')
expect(hasDetailTab(result.detailTabs, 'timing')).toBe(false)
Expand Down
12 changes: 3 additions & 9 deletions packages/chat-debug-view/test/SelectEventAtIndex.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ test('selectEventAtIndex should clear the selected event when the index is out o
],
}

const result = await selectEventAtIndex(state, 3, {
loadSelectedEvent,
})
const result = await selectEventAtIndex(state, 3, loadSelectedEvent)

expect(result).toEqual({
...state,
Expand All @@ -44,9 +42,7 @@ test('selectEventAtIndex should keep the event selected when it has no numeric e
events: [invalidEvent],
}

const result = await selectEventAtIndex(state, 0, {
loadSelectedEvent,
})
const result = await selectEventAtIndex(state, 0, loadSelectedEvent)

expect(result).toEqual({
...state,
Expand Down Expand Up @@ -92,9 +88,7 @@ test('selectEventAtIndex should preserve merged ai request and response details'
sessionId: 'session-1',
}

const result = await selectEventAtIndex(state, 0, {
loadSelectedEvent,
})
const result = await selectEventAtIndex(state, 0, loadSelectedEvent)

expect(result.selectedEvent).toEqual(
expect.objectContaining({
Expand Down
Loading