Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): Make clicking on a test in the UI open the report section and scroll to the test failure if applicable #6900

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
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 @@ -56,6 +56,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')