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): replace navigation tree with test explorer #5907

Merged
merged 30 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
076dda0
feat(ui): replace navigation tree with test explorer
userquin Jun 17, 2024
7838079
Merge branch 'refs/heads/main' into userquin/feat-add-new-test-explor…
userquin Jun 17, 2024
2f243bf
chore: remove optimization
userquin Jun 17, 2024
099a504
chore: fix lint
userquin Jun 17, 2024
b0a8491
fix: missing expand/collapse icon
userquin Jun 17, 2024
cb89c2e
Merge branch 'refs/heads/main' into userquin/feat-add-new-test-explor…
userquin Jun 17, 2024
74cb684
chore: update lock file
userquin Jun 17, 2024
722d734
chore: reduce filter font size
userquin Jun 17, 2024
eecf0ab
Merge branch 'main' into userquin/feat-add-new-test-explorer-ui
userquin Jun 18, 2024
3ad2ad4
chore: update logic for typecheck iin meta
userquin Jun 18, 2024
5b34b6b
chore: add vertical lines to the explorer
userquin Jun 18, 2024
9fc998b
chore: remove bold type from filter title
userquin Jun 18, 2024
ed60c55
chore: center vertical lines with chevron icon
userquin Jun 18, 2024
a361730
chore: simplify explorer logic
userquin Jun 18, 2024
8d996b6
chore: fix lint
userquin Jun 18, 2024
d76ead5
chore: refactor logic to resume collect on task update
userquin Jun 19, 2024
14af322
chore: collect tasks on the initial load
userquin Jun 19, 2024
41224f2
fix: wrong logic when expanding/collapsing nodes
userquin Jun 19, 2024
37af7a9
Merge branch 'refs/heads/main' into userquin/feat-add-new-test-explor…
userquin Jun 19, 2024
d03a87c
chore: add ui tests for filter
userquin Jun 19, 2024
2860209
chore: update ui tests for filter
userquin Jun 19, 2024
dc1c4dd
chore: update restore opened tasks logic
userquin Jun 19, 2024
d937709
Merge branch 'refs/heads/main' into userquin/feat-add-new-test-explor…
userquin Jun 19, 2024
a32daaa
chore: update jsdocs and hints + cleanup
userquin Jun 19, 2024
5c441d9
chore: optimize collect logic to traverse only files with pending `Ta…
userquin Jun 20, 2024
a7a80a1
chore: collect all on end run
userquin Jun 20, 2024
28caf7a
chore: update buffer and refresh interval
userquin Jun 20, 2024
9beb9c2
chore: remove setting update interval, (some entries not being refres…
userquin Jun 20, 2024
918b5cc
chore: add search syntax highlighting
userquin Jun 20, 2024
e91a0a7
chore: hide all tooltips when scrolling
userquin Jun 20, 2024
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
16 changes: 0 additions & 16 deletions packages/ui/client/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,6 @@ declare global {
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const filesFailed: typeof import('./composables/summary')['filesFailed']
const filesIgnore: typeof import('./composables/summary')['filesIgnore']
const filesRunning: typeof import('./composables/summary')['filesRunning']
const filesSkipped: typeof import('./composables/summary')['filesSkipped']
const filesSnapshotFailed: typeof import('./composables/summary')['filesSnapshotFailed']
const filesSuccess: typeof import('./composables/summary')['filesSuccess']
const filesTodo: typeof import('./composables/summary')['filesTodo']
const finished: typeof import('./composables/summary')['finished']
const getCurrentBrowserIframe: typeof import('./composables/api')['getCurrentBrowserIframe']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
Expand Down Expand Up @@ -128,22 +120,14 @@ declare global {
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const tests: typeof import('./composables/summary')['tests']
const testsFailed: typeof import('./composables/summary')['testsFailed']
const testsIgnore: typeof import('./composables/summary')['testsIgnore']
const testsSkipped: typeof import('./composables/summary')['testsSkipped']
const testsSuccess: typeof import('./composables/summary')['testsSuccess']
const testsTodo: typeof import('./composables/summary')['testsTodo']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const time: typeof import('./composables/summary')['time']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toValue: typeof import('vue')['toValue']
const toggleDark: typeof import('./composables/dark')['toggleDark']
const totalTests: typeof import('./composables/summary')['totalTests']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
Expand Down
6 changes: 3 additions & 3 deletions packages/ui/client/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ declare module 'vue' {
DashboardEntry: typeof import('./components/dashboard/DashboardEntry.vue')['default']
DetailsPanel: typeof import('./components/DetailsPanel.vue')['default']
ErrorEntry: typeof import('./components/dashboard/ErrorEntry.vue')['default']
Explorer: typeof import('./components/explorer/Explorer.vue')['default']
ExplorerItem: typeof import('./components/explorer/ExplorerItem.vue')['default']
FileDetails: typeof import('./components/FileDetails.vue')['default']
FilterStatus: typeof import('./components/FilterStatus.vue')['default']
IconAction: typeof import('./components/IconAction.vue')['default']
IconButton: typeof import('./components/IconButton.vue')['default']
Modal: typeof import('./components/Modal.vue')['default']
Expand All @@ -25,9 +28,6 @@ declare module 'vue' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
StatusIcon: typeof import('./components/StatusIcon.vue')['default']
TaskItem: typeof import('./components/TaskItem.vue')['default']
TasksList: typeof import('./components/TasksList.vue')['default']
TaskTree: typeof import('./components/TaskTree.vue')['default']
TestFilesEntry: typeof import('./components/dashboard/TestFilesEntry.vue')['default']
TestsEntry: typeof import('./components/dashboard/TestsEntry.vue')['default']
TestsFilesContainer: typeof import('./components/dashboard/TestsFilesContainer.vue')['default']
Expand Down
33 changes: 33 additions & 0 deletions packages/ui/client/components/FilterStatus.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script setup lang="ts">
defineProps<{ label: string }>()
const modelValue = defineModel<boolean | null>()
</script>

<template>
<label
class="font-light text-sm checkbox flex items-center cursor-pointer py-1 text-sm w-full gap-y-1 mb-1px"
v-bind="$attrs"
@click.prevent="modelValue = !modelValue"
>
<span
:class="[
modelValue ? 'i-carbon:checkbox-checked-filled' : 'i-carbon:checkbox',
]"
text-lg
aria-hidden="true"
/>
<input
v-model="modelValue"
type="checkbox"
sr-only
>
<span flex-1 ms-2 select-none>{{ label }}</span>
</label>
</template>

<style>
.checkbox:focus-within {
outline: none;
@apply focus-base border-b-1 !mb-none;
}
</style>
2 changes: 1 addition & 1 deletion packages/ui/client/components/IconButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defineProps<{
class="w-1.4em h-1.4em flex" :class="[{ 'bg-gray-500:35 op100': active }]"
>
<slot>
<div :class="icon" ma />
<span :class="icon" ma block />
</slot>
</button>
</template>
67 changes: 26 additions & 41 deletions packages/ui/client/components/Navigation.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<script setup lang="ts">
import { hasFailedSnapshot } from '@vitest/ws-client'
import { Tooltip as VueTooltip } from 'floating-vue'
import type { File, Task } from 'vitest'
import {
Expand All @@ -9,22 +8,20 @@ import {
currentModule,
dashboardVisible,
disableCoverage,
openedTreeItems,
showCoverage,
showDashboard,
} from '~/composables/navigation'
import { client, files, findById, isReport, runAll } from '~/composables/client'
import { client, findById, isReport, runAll, runFiles } from '~/composables/client'
import { isDark, toggleDark } from '~/composables'
import { activeFileId } from '~/composables/params'
import { explorerTree } from '~/composables/explorer'
import { initialized, shouldShowExpandAll } from '~/composables/explorer/state'

const failedSnapshot = computed(
() => files.value && hasFailedSnapshot(files.value),
)
function updateSnapshot() {
return client.rpc.updateSnapshot()
}

const toggleMode = computed(() => (isDark.value ? 'light' : 'dark'))
const toggleMode = computed(() => isDark.value ? 'light' : 'dark')

function onItemClick(task: Task) {
activeFileId.value = task.file.id
Expand All @@ -41,46 +38,42 @@ async function onRunAll(files?: File[]) {
await nextTick()
}
}
await runAll(files)
if (files?.length) {
await runFiles(files)
}
else {
await runAll()
}
}

function collapseTests() {
openedTreeItems.value = []
explorerTree.collapseAllNodes()
}

function expandTests() {
files.value.forEach((file) => {
if (!openedTreeItems.value.includes(file.id)) {
openedTreeItems.value.push(file.id)
}
})
explorerTree.expandAllNodes()
}
</script>

<template>
<!-- TODO: have test tree so the folders are also nested: test -> filename -> suite -> test -->
<TasksList
border="r base"
:tasks="files"
:on-item-click="onItemClick"
:group-by-type="true"
:nested="true"
@run="onRunAll"
>
<template #header="{ filteredTests }">
<Explorer border="r base" :on-item-click="onItemClick" :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>
<div class="flex text-lg">
<IconButton
v-show="openedTreeItems.length > 0"
v-show="!shouldShowExpandAll"
v-tooltip.bottom="'Collapse tests'"
title="Collapse tests"
:disabled="!initialized"
icon="i-carbon:collapse-all"
@click="collapseTests()"
/>
<IconButton
v-show="openedTreeItems.length === 0"
v-show="shouldShowExpandAll"
v-tooltip.bottom="'Expand tests'"
:disabled="!initialized"
title="Expand tests"
icon="i-carbon:expand-all"
@click="expandTests()"
Expand All @@ -101,10 +94,7 @@ function expandTests() {
>
<div class="i-carbon:folder-off ma" />
<template #popper>
<div
class="op100 gap-1 p-y-1"
grid="~ items-center cols-[1.5em_1fr]"
>
<div class="op100 gap-1 p-y-1" grid="~ items-center cols-[1.5em_1fr]">
<div class="i-carbon:information-square w-1.5em h-1.5em" />
<div>Coverage enabled but missing html reporter.</div>
<div style="grid-column: 2">
Expand All @@ -125,23 +115,18 @@ function expandTests() {
@click="showCoverage()"
/>
<IconButton
v-if="failedSnapshot && !isReport"
v-if="(explorerTree.summary.failedSnapshot && !isReport)"
v-tooltip.bottom="'Update all failed snapshot(s)'"
icon="i-carbon:result-old"
@click="updateSnapshot()"
:disabled="!explorerTree.summary.failedSnapshotEnabled"
@click="explorerTree.summary.failedSnapshotEnabled && updateSnapshot()"
/>
<IconButton
v-if="!isReport"
v-tooltip.bottom="
filteredTests
? filteredTests.length === 0
? 'No test to run (clear filter)'
: 'Rerun filtered'
: 'Rerun all'
"
:disabled="filteredTests?.length === 0"
v-tooltip.bottom="filteredFiles ? (filteredFiles.length === 0 ? 'No test to run (clear filter)' : 'Rerun filtered') : 'Rerun all'"
:disabled="filteredFiles?.length === 0"
icon="i-carbon:play"
@click="onRunAll(filteredTests)"
@click="onRunAll(filteredFiles)"
/>
<IconButton
v-tooltip.bottom="`Toggle to ${toggleMode} mode`"
Expand All @@ -150,5 +135,5 @@ function expandTests() {
/>
</div>
</template>
</TasksList>
</Explorer>
</template>
27 changes: 12 additions & 15 deletions packages/ui/client/components/ProgressBar.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script setup lang="ts">
import { files } from '~/composables/client'
import { filesFailed, filesSuccess, finished } from '~/composables/summary'
import { explorerTree } from '~/composables/explorer'
import { finished } from '~/composables/client/state'

const { width } = useWindowSize()
const classes = computed(() => {
// if there is no files, then in progress and gray
if (files.value.length === 0) {
// if there are no files, then in progress and gray
if (explorerTree.summary.files === 0) {
return '!bg-gray-4 !dark:bg-gray-7 in-progress'
}
else if (!finished.value) {
Expand All @@ -14,25 +14,22 @@ const classes = computed(() => {

return null
})
const total = computed(() => files.value.length)
const pass = computed(() => filesSuccess.value.length)
const failed = computed(() => filesFailed.value.length)

const widthPass = computed(() => {
const t = unref(total)
return t > 0 ? (width.value * pass.value) / t : 0
const t = explorerTree.summary.files
return t > 0 ? (width.value * explorerTree.summary.filesSuccess / t) : 0
})
const widthFailed = computed(() => {
const t = unref(total)
return t > 0 ? (width.value * failed.value) / t : 0
const t = explorerTree.summary.files
return t > 0 ? (width.value * explorerTree.summary.filesFailed / t) : 0
})
const pending = computed(() => {
const t = unref(total)
return t - failed.value - pass.value
const t = explorerTree.summary.files
return t - explorerTree.summary.filesFailed - explorerTree.summary.filesSuccess
})
const widthPending = computed(() => {
const t = unref(total)
return t > 0 ? (width.value * pending.value) / t : 0
const t = explorerTree.summary.files
return t > 0 ? (width.value * pending.value / t) : 0
})
</script>

Expand Down
Loading
Loading