Skip to content
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
7 changes: 5 additions & 2 deletions packages/ui/client/components/FilterStatus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function toggle() {

<template>
<label
class="font-light text-sm checkbox flex items-center py-1 text-sm w-full gap-y-1 mb-1px"
class="font-light text-sm checkbox w-fit flex items-center py-1 gap-y-1 mb-1px overflow-hidden"
:class="disabled ? 'cursor-not-allowed op50' : 'cursor-pointer'"
v-bind="$attrs"
@click.prevent="toggle"
Expand All @@ -26,6 +26,7 @@ function toggle() {
modelValue ? 'i-carbon:checkbox-checked-filled' : 'i-carbon:checkbox',
]"
text-lg
flex-shrink-0
aria-hidden="true"
/>
<input
Expand All @@ -34,13 +35,15 @@ function toggle() {
:disabled="disabled"
sr-only
>
<span flex-1 ms-2 select-none>{{ label }}</span>
<span flex-1 ms-2 select-none whitespace-nowrap truncate>{{ label }}</span>
</label>
</template>

<style>
.checkbox:focus-within {
outline: none;
border-color: initial;
/* don't add outline-none here => uno will add 2px to the outline */
@apply focus-base border-b-1 !mb-none;
}
</style>
6 changes: 3 additions & 3 deletions packages/ui/client/components/ProgressBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const widthPending = computed(() => {
absolute
l-0
t-0
bg-red5
bg-red-700 dark:bg-red-500
h-3px
:class="classes"
:style="`width: ${widthFailed}px;`"
Expand All @@ -61,7 +61,7 @@ const widthPending = computed(() => {
absolute
l-0
t-0
bg-green5
bg-green-700 dark:bg-green-500
h-3px
:class="classes"
:style="`left: ${widthFailed}px; width: ${widthPass}px;`"
Expand All @@ -72,7 +72,7 @@ const widthPending = computed(() => {
absolute
l-0
t-0
bg-yellow5
bg-yellow-700 dark:bg-yellow-500
h-3px
:class="classes"
:style="`left: ${widthPass + widthFailed}px; width: ${widthPending}px;`"
Expand Down
8 changes: 4 additions & 4 deletions packages/ui/client/components/StatusIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ defineProps<{
<template>
<div
v-if="state === 'pass'"
text-green-500
text-green-700 dark:text-green-500
flex-shrink-0
i-carbon:checkmark
/>
<div
v-else-if="failedSnapshot"
v-tooltip.right="'Contains failed snapshot'"
text-red-500
text-red-700 dark:text-red-500
flex-shrink-0
i-carbon:compare
/>
<div
v-else-if="state === 'fail'"
text-red-500
text-red-700 dark:text-red-500
flex-shrink-0
i-carbon:close
/>
Expand All @@ -43,5 +43,5 @@ defineProps<{
i-carbon:redo
rotate-90
/>
<div v-else text-yellow-500 flex-shrink-0 i-carbon:circle-dash animate-spin />
<div v-else text-yellow-700 dark:text-yellow-500 flex-shrink-0 i-carbon:circle-dash animate-spin />
</template>
16 changes: 13 additions & 3 deletions packages/ui/client/components/dashboard/TestFilesEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,22 @@ import ErrorEntry from './ErrorEntry.vue'
</div>
</template>

<template v-if="explorerTree.summary.filesSkipped">
<div i-carbon:redo rotate-90 />
<div>
Skip
</div>
<div class="number" text-purple-700 dark:text-purple-400>
{{ explorerTree.summary.filesSkipped }}
</div>
</template>

<template v-if="explorerTree.summary.filesFailed">
<div i-carbon-close />
<div>
Fail
</div>
<div class="number" text-red5>
<div class="number" text-red-700 dark:text-red-500>
{{ explorerTree.summary.filesFailed }}
</div>
</template>
Expand All @@ -45,7 +55,7 @@ import ErrorEntry from './ErrorEntry.vue'
<div>
Snapshot Fail
</div>
<div class="number" text-red5>
<div class="number" text-red-700 dark:text-red-500>
{{ explorerTree.summary.filesSnapshotFailed }}
</div>
</template>
Expand All @@ -55,7 +65,7 @@ import ErrorEntry from './ErrorEntry.vue'
<div>
Errors
</div>
<div class="number" text-red5>
<div class="number" text-red-700 dark:text-red-500>
{{ unhandledErrors.length }}
</div>
</template>
Expand Down
26 changes: 21 additions & 5 deletions packages/ui/client/components/dashboard/TestsEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { explorerTree } from '~/composables/explorer'
import { filter } from '~/composables/explorer/state'
import DashboardEntry from './DashboardEntry.vue'

function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'total') {
function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'slow' | 'total') {
// Reset all filters first
filter.success = false
filter.failed = false
filter.skipped = false
filter.slow = false

if (type === 'total') {
return
Expand All @@ -20,7 +21,7 @@ function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'total') {
<template>
<div flex="~ wrap" justify-evenly gap-2 p="x-4" relative>
<DashboardEntry
text-green5
text-green-700 dark:text-green-500
data-testid="pass-entry"
cursor-pointer
hover="op80"
Expand All @@ -34,7 +35,7 @@ function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'total') {
</template>
</DashboardEntry>
<DashboardEntry
:class="{ 'text-red5': explorerTree.summary.testsFailed, 'op50': !explorerTree.summary.testsFailed }"
:class="{ 'text-red-700 dark:text-red-500': explorerTree.summary.testsFailed, 'op50': !explorerTree.summary.testsFailed }"
data-testid="fail-entry"
cursor-pointer
hover="op80"
Expand All @@ -49,7 +50,7 @@ function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'total') {
</DashboardEntry>
<DashboardEntry
v-if="explorerTree.summary.testsExpectedFail"
text-cyan5
text-cyan-700 dark:text-cyan-500
data-testid="expected-fail-entry"
>
<template #header>
Expand All @@ -61,7 +62,7 @@ function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'total') {
</DashboardEntry>
<DashboardEntry
v-if="explorerTree.summary.testsSkipped"
op50
text-purple-700 dark:text-purple-400
data-testid="skipped-entry"
cursor-pointer
hover="op80"
Expand Down Expand Up @@ -100,5 +101,20 @@ function toggleFilter(type: 'success' | 'failed' | 'skipped' | 'total') {
{{ explorerTree.summary.totalTests }}
</template>
</DashboardEntry>
<DashboardEntry
v-if="explorerTree.summary.testsSlow"
text-yellow-700 dark:text-yellow-500
data-testid="slow-entry"
cursor-pointer
hover="op80"
@click="toggleFilter('slow')"
>
<template #header>
Slow
</template>
<template #body>
{{ explorerTree.summary.testsSlow }}
</template>
</DashboardEntry>
</div>
</template>
45 changes: 19 additions & 26 deletions packages/ui/client/components/explorer/Explorer.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script setup lang="ts">
import type { File, Task } from '@vitest/runner'
import { useResizeObserver } from '@vueuse/core'
import { hideAllPoppers } from 'floating-vue'
import { computed, ref } from 'vue'

Expand Down Expand Up @@ -28,6 +27,14 @@ const emit = defineEmits<{
}>()

const includeTaskLocation = computed(() => config.value.includeTaskLocation)
const slowTime = computed(() => {
const threshold = config.value.slowTestThreshold
if (typeof threshold === 'number') {
return ` (>${threshold}ms)`
}

return ''
})

const searchBox = ref<HTMLInputElement | undefined>()
const selectProjectRef = ref<HTMLSelectElement | undefined>()
Expand Down Expand Up @@ -56,25 +63,10 @@ const {
disableClearProjectSort,
searchMatcher,
} = useSearch(searchBox, selectProjectRef, sortProjectRef)

const filterClass = ref<string>('grid-cols-2')
const filterHeaderClass = ref<string>('grid-col-span-2')

const testExplorerRef = ref<HTMLElement | undefined>()
useResizeObserver(() => testExplorerRef.value, ([{ contentRect }]) => {
if (contentRect.width < 420) {
filterClass.value = 'grid-cols-2'
filterHeaderClass.value = 'grid-col-span-2'
}
else {
filterClass.value = 'grid-cols-4'
filterHeaderClass.value = 'grid-col-span-4'
}
})
</script>

<template>
<div ref="testExplorerRef" h="full" flex="~ col">
<div h="full" flex="~ col">
<div>
<div p="2" h-10 flex="~ gap-2" items-center bg-header border="b base">
<slot name="header" :filtered-files="isFiltered || isFilteredByStatus ? filteredFiles : undefined" />
Expand Down Expand Up @@ -222,18 +214,17 @@ useResizeObserver(() => testExplorerRef.value, ([{ contentRect }]) => {
items-center
bg-header
border="b-2 base"
grid="~ items-center gap-x-2 rows-[auto_auto]"
:class="filterClass"
flex="~ wrap gap-x-4 justify-between"
>
<div :class="filterHeaderClass" flex="~ gap-2 items-center">
<div aria-hidden="true" class="i-carbon:filter" />
<div min-w-full flex="~ gap-2 items-center">
<div aria-hidden="true" class="i-carbon:filter" flex-shrink-0 />
<div flex-grow-1 text-sm>
Filter
</div>
<IconButton
v-tooltip.bottom="'Clear Filter'"
:disabled="disableFilter"
title="Clear search"
title="Clear filter"
icon="i-carbon:filter-remove"
@click.passive="clearFilter(false)"
/>
Expand All @@ -242,24 +233,25 @@ useResizeObserver(() => testExplorerRef.value, ([{ contentRect }]) => {
<FilterStatus v-model="filter.success" label="Pass" />
<FilterStatus v-model="filter.skipped" label="Skip" />
<FilterStatus v-model="filter.onlyTests" label="Only Tests" />
<FilterStatus v-model="filter.slow" :label="`Slow${slowTime}`" />
</div>
</div>
<div class="scrolls" flex-auto py-1 @scroll.passive="hideAllPoppers">
<ResultsPanel>
<template v-if="initialized" #summary>
<div grid="~ items-center gap-x-1 cols-[auto_min-content_auto] rows-[min-content_min-content]">
<span text-red5>
<span text-red-700 dark:text-red-500>
FAIL ({{ testsTotal.failed }})
</span>
<span>/</span>
<span text-yellow5>
<span text-yellow-700 dark:text-yellow-500>
RUNNING ({{ testsTotal.running }})
</span>
<span text-green5>
<span text-green-700 dark:text-green-500>
PASS ({{ testsTotal.success }})
</span>
<span>/</span>
<span class="text-purple5:50">
<span class="text-purple-700 dark:text-purple-400">
SKIP ({{ filter.onlyTests ? testsTotal.skipped : '--' }})
</span>
</div>
Expand Down Expand Up @@ -343,6 +335,7 @@ useResizeObserver(() => testExplorerRef.value, ([{ contentRect }]) => {
:project-name-color="item.projectNameColor ?? ''"
:state="item.state"
:duration="item.duration"
:slow="item.slow === true"
:opened="item.expanded"
:disable-task-location="!includeTaskLocation"
:class="selectedTest === item.id || (!selectedTest && activeFileId === item.id) ? 'bg-active' : ''"
Expand Down
15 changes: 11 additions & 4 deletions packages/ui/client/components/explorer/ExplorerItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const {
indent,
name,
duration,
slow,
current,
opened,
expandable,
Expand All @@ -35,6 +36,7 @@ const {
indent: number
typecheck?: boolean
duration?: number
slow?: boolean
state?: TaskState
current: boolean
type: TaskTreeNodeType
Expand Down Expand Up @@ -212,15 +214,20 @@ const tagsBgGradient = computed(() => {
<div :class="opened ? 'i-carbon:chevron-down' : 'i-carbon:chevron-right op20'" op20 />
</div>
<StatusIcon :state="state" :mode="task.mode" :failed-snapshot="failedSnapshot" w-4 />
<div flex items-end gap-2 overflow-hidden>
<div flex items-baseline gap-2 overflow-hidden>
<div v-if="type === 'file' && typecheck" v-tooltip.bottom="'This is a typecheck test. It won\'t report results of the runtime tests'" class="i-logos:typescript-icon" flex-shrink-0 />
<span text-sm truncate font-light>
<span v-if="type === 'file' && projectName" class="rounded-full py-0.5 px-2 mr-1 text-xs" :style="{ backgroundColor: projectNameColor, color: projectNameTextColor }">
{{ projectName }}
</span>
<span :text="state === 'fail' ? 'red-500' : ''" v-html="highlighted" />
<span :class="state === 'fail' ? 'text-red-700 dark:text-red-500' : undefined" v-html="highlighted" />
</span>
<span v-if="typeof duration === 'number'" text="xs" op20 style="white-space: nowrap">
<span
v-if="typeof duration === 'number'"
text="xs"
:class="slow ? 'text-yellow-700 dark:text-yellow-500' : 'op20'"
style="white-space: nowrap"
>
{{ duration > 0 ? duration : '< 1' }}ms
</span>
</div>
Expand Down Expand Up @@ -276,7 +283,7 @@ const tagsBgGradient = computed(() => {
data-testid="btn-run-test"
:title="runButtonTitle"
icon="i-carbon:play-filled-alt"
text-green5
text-green-700 dark:text-green-500
:disabled="config.api?.allowExec === false"
@click.prevent.stop="onRun(task)"
/>
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/client/components/views/ViewEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ function createErrorElement(e: TestError) {
const div = document.createElement('div')
div.className = 'op80 flex gap-x-2 items-center'
const pre = document.createElement('pre')
pre.className = 'c-red-600 dark:c-red-400'
pre.className = 'c-red-700 dark:c-red-400'
pre.textContent = `${' '.repeat(stack.column)}^ ${e.name}: ${
e?.message || ''
}`
div.appendChild(pre)
const span = document.createElement('span')
span.className
= 'i-carbon-launch c-red-600 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em'
= 'i-carbon-launch c-red-700 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em'
span.tabIndex = 0
span.ariaLabel = 'Open in Editor'
createTooltip(
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/client/components/views/ViewReportError.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function showCode(stack: ParsedStack) {
- {{ relative(stack.file) }}:{{ stack.line }}:{{ stack.column }}</pre>
<div
v-tooltip.bottom="'Open in Editor'"
class="i-carbon-launch c-red-600 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em"
class="i-carbon-launch c-red-700 dark:c-red-400 hover:cursor-pointer min-w-1em min-h-1em"
tabindex="0"
aria-label="Open in Editor"
@click.passive="showCode(stack)"
Expand Down
Loading
Loading