Skip to content

Commit b117e87

Browse files
authored
feat(ui): load module graph on tab selection (#5844)
1 parent 4700367 commit b117e87

File tree

10 files changed

+82
-42
lines changed

10 files changed

+82
-42
lines changed

packages/ui/client/components/FileDetails.vue

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
<script setup lang="ts">
2-
import type { ModuleGraphData } from 'vitest'
32
import { client, current, currentLogs, isReport, browserState, config } from '~/composables/client'
43
import type { Params } from '~/composables/params'
54
import { viewMode } from '~/composables/params'
65
import type { ModuleGraph } from '~/composables/module-graph'
76
import { getModuleGraph } from '~/composables/module-graph'
8-
import { getProjectNameColor } from '~/utils/task';
7+
import { getProjectNameColor } from '~/utils/task'
98
10-
const data = ref<ModuleGraphData>({ externalized: [], graph: {}, inlined: [] })
119
const graph = ref<ModuleGraph>({ nodes: [], links: [] })
1210
const draft = ref(false)
1311
const hasGraphBeenDisplayed = ref(false)
12+
const loadingModuleGraph = ref(false)
13+
const currentFilepath = ref<string | undefined>(undefined)
1414
15-
debouncedWatch(
16-
current,
17-
async (c, o) => {
18-
if (c && c.filepath !== o?.filepath) {
19-
const project = c.file.projectName || ''
20-
data.value = await client.rpc.getModuleGraph(project, c.filepath, !!browserState)
21-
graph.value = getModuleGraph(data.value, c.filepath)
22-
}
23-
},
24-
{ debounce: 100, immediate: true },
25-
)
15+
const graphData = computed(() => {
16+
const c = current.value
17+
if (!c || !c.filepath)
18+
return
19+
20+
return {
21+
filepath: c.filepath,
22+
projectName: c.file.projectName || '',
23+
}
24+
})
2625
2726
function open() {
2827
const filePath = current.value?.filepath
@@ -44,12 +43,42 @@ function onDraft(value: boolean) {
4443
draft.value = value
4544
}
4645
47-
function relativeToRoot(path?: string) {
48-
if (!path) return ''
49-
if (path.startsWith(config.root))
50-
return path.slice(config.root.length)
51-
return path
46+
async function loadModuleGraph() {
47+
if (loadingModuleGraph.value || graphData.value?.filepath === currentFilepath.value)
48+
return
49+
50+
loadingModuleGraph.value = true
51+
52+
await nextTick()
53+
54+
try {
55+
const gd = graphData.value
56+
if (!gd)
57+
return
58+
59+
if (!currentFilepath.value || gd.filepath !== currentFilepath.value || (!graph.value.nodes.length && !graph.value.links.length)) {
60+
graph.value = getModuleGraph(
61+
await client.rpc.getModuleGraph(gd.projectName, gd.filepath, !!browserState),
62+
gd.filepath,
63+
)
64+
currentFilepath.value = gd.filepath
65+
}
66+
changeViewMode('graph')
67+
}
68+
finally {
69+
await new Promise(resolve => setTimeout(resolve, 100))
70+
loadingModuleGraph.value = false
71+
}
5272
}
73+
74+
debouncedWatch(
75+
() => [graphData.value, viewMode.value] as const,
76+
([, vm]) => {
77+
if (vm === 'graph')
78+
loadModuleGraph()
79+
},
80+
{ debounce: 100, immediate: true },
81+
)
5382
</script>
5483

5584
<template>
@@ -61,7 +90,7 @@ function relativeToRoot(path?: string) {
6190
[{{ current?.file.projectName || '' }}]
6291
</div>
6392
<div flex-1 font-light op-50 ws-nowrap truncate text-sm>
64-
{{ relativeToRoot(current?.filepath) }}
93+
{{ current?.name }}
6594
</div>
6695
<div class="flex text-lg">
6796
<IconButton
@@ -77,43 +106,52 @@ function relativeToRoot(path?: string) {
77106
<div flex="~" items-center bg-header border="b-2 base" text-sm h-41px>
78107
<button
79108
tab-button
109+
class="flex items-center gap-2"
80110
:class="{ 'tab-button-active': viewMode == null }"
81111
data-testid="btn-report"
82112
@click="changeViewMode(null)"
83113
>
114+
<span class="block w-1.4em h-1.4em i-carbon:report"></span>
84115
Report
85116
</button>
86117
<button
87118
tab-button
88119
data-testid="btn-graph"
120+
class="flex items-center gap-2"
89121
:class="{ 'tab-button-active': viewMode === 'graph' }"
90122
@click="changeViewMode('graph')"
91123
>
124+
<span v-if="loadingModuleGraph" class="block w-1.4em h-1.4em i-carbon:circle-dash animate-spin animate-2s"></span>
125+
<span v-else class="block w-1.4em h-1.4em i-carbon:chart-relationship"></span>
92126
Module Graph
93127
</button>
94128
<button
95129
v-if="!isReport"
96130
tab-button
97131
data-testid="btn-code"
132+
class="flex items-center gap-2"
98133
:class="{ 'tab-button-active': viewMode === 'editor' }"
99134
@click="changeViewMode('editor')"
100135
>
136+
<span class="block w-1.4em h-1.4em i-carbon:code"></span>
101137
{{ draft ? '*&#160;' : '' }}Code
102138
</button>
103139
<button
104140
tab-button
105141
data-testid="btn-console"
142+
class="flex items-center gap-2"
106143
:class="{ 'tab-button-active': viewMode === 'console', 'op20': viewMode !== 'console' && consoleCount === 0 }"
107144
@click="changeViewMode('console')"
108145
>
146+
<span class="block w-1.4em h-1.4em i-carbon:terminal-3270"></span>
109147
Console ({{ consoleCount }})
110148
</button>
111149
</div>
112150
</div>
113151

114152
<div flex flex-col flex-1 overflow="hidden">
115153
<div v-if="hasGraphBeenDisplayed" :flex-1="viewMode === 'graph' && ''">
116-
<ViewModuleGraph v-show="viewMode === 'graph'" :graph="graph" data-testid="graph" :project-name="current.file.projectName || ''" />
154+
<ViewModuleGraph v-show="viewMode === 'graph' && !loadingModuleGraph" :graph="graph" data-testid="graph" :project-name="current.file.projectName || ''" />
117155
</div>
118156
<ViewEditor v-if="viewMode === 'editor'" :key="current.filepath" :file="current" data-testid="editor" @draft="onDraft" />
119157
<ViewConsoleOutput v-else-if="viewMode === 'console'" :file="current" data-testid="console" />

packages/ui/client/components/Navigation.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import {
1111
disableCoverage,
1212
showCoverage,
1313
showDashboard,
14-
} from '../composables/navigation'
15-
import { client, findById } from '../composables/client'
14+
} from '~/composables/navigation'
15+
import { client, findById } from '~/composables/client'
1616
import { isDark, toggleDark } from '~/composables'
1717
import { files, isReport, runAll } from '~/composables/client'
1818
import { activeFileId } from '~/composables/params'
@@ -63,18 +63,18 @@ function expandTests() {
6363
<img w-6 h-6 src="/favicon.svg" alt="Vitest logo">
6464
<span font-light text-sm flex-1>Vitest</span>
6565
<div class="flex text-lg">
66-
<IconButton
66+
<IconButton
6767
v-show="openedTreeItems.length > 0"
6868
v-tooltip.bottom="'Collapse tests'"
6969
title="Collapse tests"
70-
icon="i-carbon:collapse-all"
70+
icon="i-carbon:collapse-all"
7171
@click="collapseTests()"
7272
/>
73-
<IconButton
73+
<IconButton
7474
v-show="openedTreeItems.length === 0"
7575
v-tooltip.bottom="'Expand tests'"
7676
title="Expand tests"
77-
icon="i-carbon:expand-all"
77+
icon="i-carbon:expand-all"
7878
@click="expandTests()"
7979
/>
8080
<IconButton

packages/ui/client/components/ProgressBar.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
2-
import { files } from '../composables/client'
3-
import { filesFailed, filesSuccess, finished } from '../composables/summary'
2+
import { files } from '~/composables/client'
3+
import { filesFailed, filesSuccess, finished } from '~/composables/summary'
44
55
const { width } = useWindowSize()
66
const classes = computed(() => {

packages/ui/client/components/dashboard/DashboardEntry.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
withDefaults(defineProps<{ tail?: boolean }>(), { tail: false })
2+
// const { tail = false } = defineProps<{ tail?: boolean }>()
33
</script>
44

55
<template>

packages/ui/client/components/dashboard/ErrorEntry.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<script setup lang="ts">
2-
const props = defineProps<{
3-
error: ErrorWithDiff
4-
}>()
2+
import type { ErrorWithDiff } from '@vitest/utils'
3+
4+
defineProps<{
5+
error: ErrorWithDiff
6+
}>()
57
</script>
68

79
<template>

packages/ui/client/components/dashboard/TestFilesEntry.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
2-
import { files, unhandledErrors } from '../../composables/client'
3-
import { filesFailed, filesSnapshotFailed, filesSuccess, time } from '../../composables/summary'
2+
import { files, unhandledErrors } from '~/composables/client'
3+
import { filesFailed, filesSnapshotFailed, filesSuccess, time } from '~/composables/summary'
44
</script>
55

66
<template>

packages/ui/client/components/dashboard/TestsEntry.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { tests, testsFailed, testsSkipped, testsSuccess, testsTodo } from '../../composables/summary'
2+
import { tests, testsFailed, testsSkipped, testsSuccess, testsTodo } from '~/composables/summary'
33
44
const total = computed(() => tests.value.length)
55
const pass = computed(() => testsSuccess.value.length)

packages/ui/client/components/views/ViewEditor.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import type CodeMirror from 'codemirror'
44
import type { ErrorWithDiff, File } from 'vitest'
55
import { createTooltip, destroyTooltip } from 'floating-vue'
6-
import { openInEditor } from '../../composables/error'
6+
import { openInEditor } from '~/composables/error'
77
import { client } from '~/composables/client'
88
99
const props = defineProps<{

packages/ui/client/components/views/ViewReportError.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import type { ErrorWithDiff } from 'vitest'
33
import { openInEditor, shouldOpenInEditor } from '~/composables/error'
4-
import { escapeHtml } from '~/utils/escape';
4+
import { escapeHtml } from '~/utils/escape'
55
66
const props = defineProps<{
77
root: string

packages/ui/client/pages/index.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,19 @@ function resizeMain() {
3939
<Navigation />
4040
</Pane>
4141
<Pane :size="mainSizes[1]">
42-
<transition v-if="!browserState">
42+
<transition v-if="!browserState" key="ui-detail">
4343
<Dashboard v-if="dashboardVisible" key="summary" />
4444
<Coverage v-else-if="coverageVisible" key="coverage" :src="coverageUrl" />
45-
<FileDetails v-else />
45+
<FileDetails v-else key="details" />
4646
</transition>
47-
<Splitpanes v-else key="detail" id="details-splitpanes" @resize="onBrowserPanelResizing(true)" @resized="onModuleResized">
47+
<Splitpanes v-else key="browser-detail" id="details-splitpanes" @resize="onBrowserPanelResizing(true)" @resized="onModuleResized">
4848
<Pane :size="detailSizes[0]" min-size="10">
4949
<BrowserIframe v-once />
5050
</Pane>
5151
<Pane :size="detailSizes[1]" min-size="5">
5252
<Dashboard v-if="dashboardVisible" key="summary" />
5353
<Coverage v-else-if="coverageVisible" key="coverage" :src="coverageUrl" />
54-
<FileDetails v-else />
54+
<FileDetails v-else key="details" />
5555
</Pane>
5656
</Splitpanes>
5757
</Pane>

0 commit comments

Comments
 (0)