Skip to content

Commit cd63e9e

Browse files
hi-ogawaOpenCode (gpt-5.6-sol)
andauthored
feat(ui): toggle trace target highlight (#11049)
Co-authored-by: Hiroshi Ogawa <4232207+hi-ogawa@users.noreply.github.com> Co-authored-by: OpenCode (gpt-5.6-sol) <noreply@opencode.ai>
1 parent 1e9f80e commit cd63e9e

4 files changed

Lines changed: 38 additions & 3 deletions

File tree

‎packages/ui/client/components/trace/TraceView.vue‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { createCache, createMirror, rebuild } from 'rrweb-snapshot'
44
import { Pane, Splitpanes } from 'splitpanes'
55
import { computed, ref, watch } from 'vue'
66
import { openLocation } from '~/composables/location'
7-
import { getTraceEntryClass, selectActiveTraceStep } from '~/composables/trace-view'
7+
import { getTraceEntryClass, selectActiveTraceStep, showTraceSelectorHighlight } from '~/composables/trace-view'
88
99
const props = defineProps<{
1010
trace: NormalizedBrowserTraceData
@@ -120,12 +120,21 @@ watch([selectedStep, iframeEl], ([step, iframe]) => {
120120
border: 2px solid #3b82f6;
121121
box-sizing: border-box;
122122
`
123+
overlay.style.display = showTraceSelectorHighlight.value ? '' : 'none'
123124
doc.documentElement.appendChild(overlay)
124125
})
125126
}
126127
}
127128
}, { immediate: true })
128129
130+
watch(showTraceSelectorHighlight, (show) => {
131+
const overlay = iframeEl.value?.contentDocument
132+
?.querySelector<HTMLElement>('[data-testid="trace-view-highlight"]')
133+
if (overlay) {
134+
overlay.style.display = show ? '' : 'none'
135+
}
136+
})
137+
129138
function getStepButtonClass(step: NormalizedBrowserTraceEntry, index: number) {
130139
const selected = props.selection.selectedStepIndex === index
131140
// TODO: move trace step state colors to shared semantic UI shortcuts.

‎packages/ui/client/components/trace/TraceViewPane.vue‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import type { TraceSelection } from '~/composables/trace-view'
33
import { computed } from 'vue'
44
import IconButton from '~/components/IconButton.vue'
5-
import { closeTrace, getSelectedTrace, getTraceAttemptLabel } from '~/composables/trace-view'
5+
import { closeTrace, getSelectedTrace, getTraceAttemptLabel, showTraceSelectorHighlight } from '~/composables/trace-view'
66
import TraceView from './TraceView.vue'
77
88
const props = defineProps<{
@@ -25,6 +25,13 @@ const attemptLabel = computed(() => trace.value ? getTraceAttemptLabel(trace.val
2525
>
2626
{{ attemptLabel }}
2727
</span>
28+
<label class="flex items-center gap-1 text-xs ws-nowrap select-none cursor-pointer">
29+
<input
30+
v-model="showTraceSelectorHighlight"
31+
type="checkbox"
32+
>
33+
<span>Show highlight</span>
34+
</label>
2835
<IconButton
2936
v-tooltip.bottom="'Close Trace Viewer'"
3037
title="Close Trace Viewer"

‎packages/ui/client/composables/trace-view.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { RunnerTestCase, RunnerTestFile, TestArtifact } from 'vitest'
22
import type { BrowserTraceData, BrowserTraceEntry } from '../../../browser/src/client/tester/trace'
3+
import { useLocalStorage } from '@vueuse/core'
34
import { computed, ref, watch, watchEffect } from 'vue'
45
import { getProjectConfigByName } from '~/utils/task'
56
import { browserState, client, config } from './client'
@@ -30,6 +31,11 @@ export interface NormalizedBrowserTraceEntry extends BrowserTraceEntry {
3031

3132
export const activeTraceView = ref<TraceSelection>()
3233

34+
export const showTraceSelectorHighlight = useLocalStorage(
35+
'vitest-ui_trace-selector-highlight',
36+
true,
37+
)
38+
3339
function getTraceAttemptKey(trace: BrowserTraceData): string {
3440
return `${trace.repeats}:${trace.retry}`
3541
}

‎test/ui/test/trace.spec.ts‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,20 @@ async function testBasic(page: Page) {
192192
await expect(traceFrame.getByRole('button', { name: 'Simple' })).toBeVisible()
193193

194194
// verify selector highlight
195-
await expect(traceFrame.getByTestId('trace-view-highlight')).toBeVisible()
195+
const traceHighlight = traceFrame.getByTestId('trace-view-highlight')
196+
const showHighlightCheckbox = traceView.getByRole('checkbox', { name: 'Show highlight' })
197+
await expect(traceHighlight).toBeVisible()
198+
await expect(showHighlightCheckbox).toBeChecked()
199+
200+
// hide selector highlight and persist preference across reloads
201+
await showHighlightCheckbox.uncheck()
202+
await expect(traceHighlight).toBeHidden()
203+
await page.reload()
204+
await expect(traceView).toBeVisible()
205+
await expect(traceHighlight).toBeHidden()
206+
await expect(showHighlightCheckbox).not.toBeChecked()
207+
await showHighlightCheckbox.check()
208+
await expect(traceHighlight).toBeVisible()
196209

197210
// selecting 2nd trace step with keyboard and verify again
198211
await traceSteps.nth(0).press('ArrowDown')

0 commit comments

Comments
 (0)