Skip to content

Commit

Permalink
feat(ui): Make clicking on a test in the UI open the report section a…
Browse files Browse the repository at this point in the history
…nd scroll to the test failure if applicable (#6900)
  • Loading branch information
jacoberdman2147 authored Dec 9, 2024
1 parent f691ad7 commit 1bf27f0
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 16 deletions.
2 changes: 2 additions & 0 deletions packages/ui/client/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ declare global {
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const selectedTest: typeof import('./composables/params')['selectedTest']
const setIframeViewport: typeof import('./composables/api')['setIframeViewport']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
Expand All @@ -127,6 +128,7 @@ declare global {
const showDashboard: typeof import('./composables/navigation')['showDashboard']
const showLine: typeof import('./composables/codemirror')['showLine']
const showNavigationPanel: typeof import('./composables/navigation')['showNavigationPanel']
const showReport: typeof import('./composables/navigation')['showReport']
const showRightPanel: typeof import('./composables/navigation')['showRightPanel']
const showSource: typeof import('./composables/codemirror')['showSource']
const syncRef: typeof import('@vueuse/core')['syncRef']
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/client/components/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import {
coverageVisible,
dashboardVisible,
disableCoverage,
navigateTo,
showCoverage,
showDashboard,
showReport,
} from '~/composables/navigation'
function updateSnapshot() {
Expand Down Expand Up @@ -50,7 +50,7 @@ function expandTests() {

<template>
<!-- TODO: have test tree so the folders are also nested: test -> filename -> suite -> test -->
<Explorer border="r base" :on-item-click="navigateTo" :nested="true" @run="onRunAll">
<Explorer border="r base" :on-item-click="showReport" :nested="true" @run="onRunAll">
<template #header="{ filteredFiles }">
<img w-6 h-6 src="/favicon.svg" alt="Vitest logo">
<span font-light text-sm flex-1>Vitest</span>
Expand Down
1 change: 1 addition & 0 deletions packages/ui/client/components/explorer/ExplorerItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const failedSnapshot = computed(() => {
function toggleOpen() {
if (!expandable) {
onItemClick?.(task.value!)
return
}
Expand Down
15 changes: 14 additions & 1 deletion packages/ui/client/components/views/ViewReport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { ErrorWithDiff, File, Suite, Task } from 'vitest'
import { browserState, config } from '~/composables/client'
import { isDark } from '~/composables/dark'
import { createAnsiToHtmlFilter } from '~/composables/error'
import { selectedTest } from '~/composables/params'
import { escapeHtml } from '~/utils/escape'
const props = defineProps<{
Expand Down Expand Up @@ -127,12 +128,24 @@ function showScreenshotModal(task: Task) {
timestamp.value = Date.now()
showScreenshot.value = true
}
watch(() => [selectedTest.value] as const, ([test]) => {
if (test != null) {
// Have to wrap the selector in [id=''] since #{test} will produce an invalid selector because the test ID is a number
const testElement = document.querySelector(`[id='${test}'`)
if (testElement != null) {
nextTick(() => {
testElement.scrollIntoView()
})
}
}
}, { flush: 'post' })
</script>

<template>
<div h-full class="scrolls">
<template v-if="failed.length">
<div v-for="task of failed" :key="task.id">
<div v-for="task of failed" :id="task.id" :key="task.id">
<div
bg="red-500/10"
text="red-500 sm"
Expand Down
7 changes: 6 additions & 1 deletion packages/ui/client/composables/codemirror.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,10 @@ export function useCodeMirror(
}

export async function showSource(task: Task) {
navigateTo(task, task.location?.line ?? 0)
navigateTo({
file: task.file.id,
line: task.location?.line ?? 0,
view: 'editor',
test: null,
})
}
29 changes: 17 additions & 12 deletions packages/ui/client/composables/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { File, Task } from '@vitest/runner'
import type { Params } from './params'
import { client, config, findById } from './client'
import { testRunState } from './client/state'
import { activeFileId, lineNumber, viewMode } from './params'
import { activeFileId, lineNumber, selectedTest, viewMode } from './params'

export const currentModule = ref<File>()
export const dashboardVisible = ref(true)
Expand Down Expand Up @@ -99,20 +100,24 @@ export function showDashboard(show: boolean) {
}
}

export function navigateTo(task: Task, line: number | null = null) {
activeFileId.value = task.file.id
// reset line number
lineNumber.value = null
if (line != null) {
nextTick(() => {
lineNumber.value = line
})
viewMode.value = 'editor'
}
currentModule.value = findById(task.file.id)
export function navigateTo({ file, line, view, test }: Params) {
activeFileId.value = file
lineNumber.value = line
viewMode.value = view
selectedTest.value = test
currentModule.value = findById(file)
showDashboard(false)
}

export function showReport(task: Task) {
navigateTo({
file: task.file.id,
test: task.type === 'test' ? task.id : null,
line: null,
view: null,
})
}

export function showCoverage() {
coverageVisible.value = true
dashboardVisible.value = false
Expand Down
3 changes: 3 additions & 0 deletions packages/ui/client/composables/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ export interface Params {
file: string
view: null | 'graph' | 'editor' | 'console'
line: null | number
test: null | string
}

export const params = useUrlSearchParams<Params>('hash', {
initialValue: {
file: '',
view: null,
line: null,
test: null,
},
})

export const activeFileId = toRef(params, 'file')
export const viewMode = toRef(params, 'view')
export const lineNumber = toRef(params, 'line')
export const selectedTest = toRef(params, 'test')

0 comments on commit 1bf27f0

Please sign in to comment.