Skip to content

feat(ui): add action to explorer item to show the test/suite line in the source code tab #5948

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

Merged
merged 11 commits into from
Jun 27, 2024
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 @@ -62,6 +62,7 @@ declare global {
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const lineNumber: typeof import('./composables/params')['lineNumber']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const markRaw: typeof import('vue')['markRaw']
const navigateTo: typeof import('./composables/navigation')['navigateTo']
Expand Down Expand Up @@ -108,6 +109,7 @@ declare global {
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const registerInitializeListener: typeof import('./composables/codemirror')['registerInitializeListener']
const registerResizingListener: typeof import("./composables/browser")["registerResizingListener"]
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/client/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
BrowserIframe: typeof import('./components/BrowserIframe.vue')['default']
CodeMirror: typeof import('./components/CodeMirror.vue')['default']
CodeMirrorContainer: typeof import('./components/CodeMirrorContainer.vue')['default']
ConnectionOverlay: typeof import('./components/ConnectionOverlay.vue')['default']
Coverage: typeof import('./components/Coverage.vue')['default']
Dashboard: typeof import('./components/Dashboard.vue')['default']
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/client/components/ModuleTransformResultView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ onKeyStroke('Escape', () => {
<div p="x3 y-1" bg-overlay border="base b t">
Transformed
</div>
<CodeMirror
<CodeMirrorContainer
h-full
:model-value="source"
read-only
v-bind="{ lineNumbers: true }"
:mode="ext"
/>
<CodeMirror
<CodeMirrorContainer
h-full
:model-value="code"
read-only
Expand All @@ -71,7 +71,7 @@ onKeyStroke('Escape', () => {
<div p="x3 y-1" bg-overlay border="base b t">
Source map (v{{ sourceMap.version }})
</div>
<CodeMirror
<CodeMirrorContainer
:model-value="sourceMap.mappings"
read-only
v-bind="{ lineNumbers: true }"
Expand Down
44 changes: 37 additions & 7 deletions packages/ui/client/components/views/ViewEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createTooltip, destroyTooltip } from 'floating-vue'
import { openInEditor } from '~/composables/error'
import { client, isReport } from '~/composables/client'
import { codemirrorRef } from '~/composables/codemirror'
import { lineNumber } from '~/composables/params'

const props = defineProps<{
file?: File
Expand All @@ -15,23 +16,52 @@ const emit = defineEmits<{ (event: 'draft', value: boolean): void }>()
const code = ref('')
const serverCode = shallowRef<string | undefined>(undefined)
const draft = ref(false)
const loading = ref(true)

watch(
() => props.file,
async () => {
if (!props.file || !props.file?.filepath) {
code.value = ''
loading.value = true
try {
if (!props.file || !props.file?.filepath) {
code.value = ''
serverCode.value = code.value
draft.value = false
return
}

code.value = (await client.rpc.readTestFile(props.file.filepath)) || ''
serverCode.value = code.value
draft.value = false
return
}
code.value = (await client.rpc.readTestFile(props.file.filepath)) || ''
serverCode.value = code.value
draft.value = false
finally {
// fire focusing editor after loading
nextTick(() => (loading.value = false))
}
},
{ immediate: true },
)

watch(() => [loading.value, props.file, lineNumber.value] as const, ([loadingFile, _, l]) => {
if (!loadingFile) {
if (l != null) {
nextTick(() => {
const line = { line: l ?? 0, ch: 0 }
codemirrorRef.value?.scrollIntoView(line, 100)
nextTick(() => {
codemirrorRef.value?.focus()
codemirrorRef.value?.setCursor(line)
})
})
}
else {
nextTick(() => {
codemirrorRef.value?.focus()
})
}
}
}, { flush: 'post' })

const ext = computed(() => props.file?.filepath?.split(/\./g).pop() || 'js')
const editor = ref<any>()

Expand Down Expand Up @@ -147,7 +177,7 @@ async function onSave(content: string) {
</script>

<template>
<CodeMirror
<CodeMirrorContainer
ref="editor"
v-model="code"
h-full
Expand Down
16 changes: 1 addition & 15 deletions packages/ui/client/composables/codemirror.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,5 @@ export function useCodeMirror(
}

export async function showSource(task: Task) {
const codeMirror = codemirrorRef.value
if (!codeMirror || activeFileId.value !== task.file.id) {
navigateTo(task, true)
// we need to await, CodeMirrow will take some time to initialize
await new Promise(r => setTimeout(r, 256))
}

nextTick(() => {
const line = { line: task.location?.line ?? 0, ch: 0 }
codemirrorRef.value?.scrollIntoView(line)
nextTick(() => {
codemirrorRef.value?.focus()
codemirrorRef.value?.setCursor(line)
})
})
navigateTo(task, task.location?.line ?? 0)
}
11 changes: 8 additions & 3 deletions packages/ui/client/composables/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { File, Task } from '@vitest/runner'
import { client, config, findById } from './client'
import { testRunState } from './client/state'
import { activeFileId, viewMode } from './params'
import { activeFileId, lineNumber, viewMode } from './params'

export const currentModule = ref<File>()
export const dashboardVisible = ref(true)
Expand Down Expand Up @@ -89,9 +89,14 @@ export function showDashboard(show: boolean) {
}
}

export function navigateTo(task: Task, editor = false) {
export function navigateTo(task: Task, line: number | null = null) {
activeFileId.value = task.file.id
if (editor) {
// reset line number
lineNumber.value = null
if (line != null) {
nextTick(() => {
lineNumber.value = line
})
viewMode.value = 'editor'
}
currentModule.value = findById(task.file.id)
Expand Down
3 changes: 3 additions & 0 deletions packages/ui/client/composables/params.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
export interface Params {
file: string
view: null | 'graph' | 'editor' | 'console'
line: null | number
}

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

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