Skip to content

Commit

Permalink
feat(ui): rerun status
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Dec 30, 2021
1 parent 9b9b503 commit c0ecf19
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 76 deletions.
2 changes: 1 addition & 1 deletion packages/ui/client/components/FileDetails.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { client, current } from '~/composables/client'
import { current } from '~/composables/client'
function open() {
if (current.value?.filepath)
Expand Down
6 changes: 1 addition & 5 deletions packages/ui/client/components/Navigation.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
<script setup lang="ts">
import type { Task } from '#types'
import { toggleDark } from '~/composables'
import { activeFileIdRef, client, files } from '~/composables/client'
import { activeFileIdRef, files, runAll } from '~/composables/client'
function onItemClick(task: Task) {
activeFileIdRef.value = task.id
}
function runAll() {
client.rpc.rerun(client.state.getFiles().map(i => i.filepath))
}
</script>

<template>
Expand Down
9 changes: 2 additions & 7 deletions packages/ui/client/components/Suites.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
<script setup lang="ts">
import { client, current } from '~/composables/client'
import { current, runCurrent } from '~/composables/client'
const name = computed(() => current.value?.name.split(/\//g).pop())
function run() {
if (current.value?.filepath)
client.rpc.rerun([current.value.filepath])
}
</script>

<template>
Expand All @@ -28,7 +23,7 @@ function run() {
{{ name }}
</span>
<div class="flex text-lg">
<IconButton icon="i-carbon-play" @click="run()" />
<IconButton icon="i-carbon-play" @click="runCurrent()" />
</div>
</template>
</TasksList>
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/client/components/TaskItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const props = defineProps<{
const duration = computed(() => {
const { result } = props.task
return result && result.end ? Math.round(result.end - result.start) : 0
return result && Math.round(result.duration || 0)
})
</script>

Expand All @@ -24,7 +24,7 @@ const duration = computed(() => {
<StatusIcon :task="task" mr-2 />
<div flex items-end gap-2 :text="task?.result?.state === 'fail' ? 'red-500' : ''">
<span text-sm truncate font-light>{{ task.name }}</span>
<span v-if="task.result?.end" text="xs" op20>
<span v-if="duration" text="xs" op20>
{{ duration }}ms
</span>
</div>
Expand Down
20 changes: 19 additions & 1 deletion packages/ui/client/composables/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { createClient } from '@vitest/ws-client'
import type { WebSocketStatus } from '@vueuse/core'
import { reactive } from 'vue'
import type { ResolvedConfig } from '#types'
import { getTasks } from '../../../vitest/src/utils/tasks'
import type { File, ResolvedConfig } from '#types'

export const params = useUrlSearchParams<{ file: string }>('hash-params', {
initialValue: {
Expand All @@ -28,6 +29,23 @@ export const isConnected = computed(() => status.value === 'OPEN')
export const isConnecting = computed(() => status.value === 'CONNECTING')
export const isDisconned = computed(() => status.value === 'CLOSED')

export function runAll() {
return runFiles(client.state.getFiles())
}

export function runFiles(files: File[]) {
files.forEach((f) => {
delete f.result
getTasks(f).forEach(i => delete i.result)
})
return client.rpc.rerun(files.map(i => i.filepath))
}

export function runCurrent() {
if (current.value)
return runFiles([current.value])
}

watch(
() => client.ws,
(ws) => {
Expand Down
64 changes: 4 additions & 60 deletions packages/vitest/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,12 @@ import { fileURLToPath, pathToFileURL } from 'url'
import c from 'picocolors'
import { isPackageExists } from 'local-pkg'
import { dirname, resolve } from 'pathe'
import type { Arrayable, Nullable, Suite, Task, Test } from '../types'
import type { Suite, Task } from '../types'
import { getNames, slash } from './tasks'

export const isWindows = process.platform === 'win32'

/**
* Convert `Arrayable<T>` to `Array<T>`
*
* @category Array
*/
export function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T> {
array = array || []
if (Array.isArray(array))
return array
return [array]
}

export function notNullish<T>(v: T | null | undefined): v is NonNullable<T> {
return v != null
}
export * from './tasks'

export function slash(str: string) {
return str.replace(/\\/g, '/')
}

export function mergeSlashes(str: string) {
return str.replace(/\/\//g, '/')
}

export const noop = () => {}
export const isWindows = process.platform === 'win32'

/**
* Partition in tasks groups by consecutive concurrent
Expand All @@ -53,39 +30,6 @@ export function partitionSuiteChildren(suite: Suite) {
return tasksGroups
}

export function getTests(suite: Arrayable<Task>): Test[] {
return toArray(suite).flatMap(s => s.type === 'test' ? [s] : s.tasks.flatMap(c => c.type === 'test' ? [c] : getTests(c)))
}

export function getTasks(tasks: Arrayable<Task>): Task[] {
return toArray(tasks).flatMap(s => s.type === 'test' ? [s] : [s, ...getTasks(s.tasks)])
}

export function getSuites(suite: Arrayable<Task>): Suite[] {
return toArray(suite).flatMap(s => s.type === 'suite' ? [s, ...getSuites(s.tasks)] : [])
}

export function hasTests(suite: Arrayable<Suite>): boolean {
return toArray(suite).some(s => s.tasks.some(c => c.type === 'test' || hasTests(c as Suite)))
}

export function hasFailed(suite: Arrayable<Task>): boolean {
return toArray(suite).some(s => s.result?.state === 'fail' || (s.type === 'suite' && hasFailed(s.tasks)))
}

export function getNames(task: Task) {
const names = [task.name]
let current: Task | undefined = task

while (current?.suite || current?.file) {
current = current.suite || current.file
if (current?.name)
names.unshift(current.name)
}

return names
}

export function getFullName(task: Task) {
return getNames(task).join(c.dim(' > '))
}
Expand Down
60 changes: 60 additions & 0 deletions packages/vitest/src/utils/tasks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { Arrayable, Nullable, Suite, Task, Test } from '../types'

export function notNullish<T>(v: T | null | undefined): v is NonNullable<T> {
return v != null
}

export function slash(str: string) {
return str.replace(/\\/g, '/')
}

export function mergeSlashes(str: string) {
return str.replace(/\/\//g, '/')
}

export const noop = () => {}

/**
* Convert `Arrayable<T>` to `Array<T>`
*
* @category Array
*/
export function toArray<T>(array?: Nullable<Arrayable<T>>): Array<T> {
array = array || []
if (Array.isArray(array))
return array
return [array]
}

export function getTests(suite: Arrayable<Task>): Test[] {
return toArray(suite).flatMap(s => s.type === 'test' ? [s] : s.tasks.flatMap(c => c.type === 'test' ? [c] : getTests(c)))
}

export function getTasks(tasks: Arrayable<Task>): Task[] {
return toArray(tasks).flatMap(s => s.type === 'test' ? [s] : [s, ...getTasks(s.tasks)])
}

export function getSuites(suite: Arrayable<Task>): Suite[] {
return toArray(suite).flatMap(s => s.type === 'suite' ? [s, ...getSuites(s.tasks)] : [])
}

export function hasTests(suite: Arrayable<Suite>): boolean {
return toArray(suite).some(s => s.tasks.some(c => c.type === 'test' || hasTests(c as Suite)))
}

export function hasFailed(suite: Arrayable<Task>): boolean {
return toArray(suite).some(s => s.result?.state === 'fail' || (s.type === 'suite' && hasFailed(s.tasks)))
}

export function getNames(task: Task) {
const names = [task.name]
let current: Task | undefined = task

while (current?.suite || current?.file) {
current = current.suite || current.file
if (current?.name)
names.unshift(current.name)
}

return names
}

0 comments on commit c0ecf19

Please sign in to comment.