diff --git a/.eslintrc b/.eslintrc index cd92a58cd70b..018a2f1c078c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -23,6 +23,18 @@ } ] } + }, + { + // these files define vitest as peer dependency + "files": "packages/{coverage-*,ui,browser}/**/*.*", + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": ["path"] + } + ] + } } ] } diff --git a/docs/config/index.md b/docs/config/index.md index 2ddc87a9e988..37ba61e626e6 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -776,6 +776,8 @@ The reporter has three different types: } ``` +Since Vitest 0.31.0, you can check your coverage report in Vitest UI: check [Vitest UI Coverage](/guide/coverage#vitest-ui) for more details. + #### coverage.skipFull - **Type:** `boolean` diff --git a/docs/guide/coverage.md b/docs/guide/coverage.md index 493b22c3e091..14e5ea3ebc63 100644 --- a/docs/guide/coverage.md +++ b/docs/guide/coverage.md @@ -164,3 +164,15 @@ if (condition) { ## Other Options To see all configurable options for coverage, see the [coverage Config Reference](https://vitest.dev/config/#coverage). + +## Vitest UI + +Since Vitest 0.31.0, you can check your coverage report in [Vitest UI](./ui). + +If you have configured coverage reporters, don't forget to add `html` reporter to the list, Vitest UI will only enable html coverage report if it is present. + + + + + + diff --git a/docs/guide/ui.md b/docs/guide/ui.md index 4f6f146ba77e..3371430c1538 100644 --- a/docs/guide/ui.md +++ b/docs/guide/ui.md @@ -34,6 +34,8 @@ export default { } ``` +Since Vitest 0.31.0, you can check your coverage report in Vitest UI: check [Vitest UI Coverage](/guide/coverage#vitest-ui) for more details. + ::: warning If you still want to see how your tests are running in real time in the terminal, don't forget to add `default` reporter to `reporters` option: `['default', 'html']`. ::: diff --git a/docs/public/vitest-ui-coverage-dark.png b/docs/public/vitest-ui-coverage-dark.png new file mode 100644 index 000000000000..bdfd3ac0e51b Binary files /dev/null and b/docs/public/vitest-ui-coverage-dark.png differ diff --git a/docs/public/vitest-ui-coverage-light.png b/docs/public/vitest-ui-coverage-light.png new file mode 100644 index 000000000000..2f78be630177 Binary files /dev/null and b/docs/public/vitest-ui-coverage-light.png differ diff --git a/docs/public/vitest-ui-show-coverage-dark.png b/docs/public/vitest-ui-show-coverage-dark.png new file mode 100644 index 000000000000..fdb7acc5ec02 Binary files /dev/null and b/docs/public/vitest-ui-show-coverage-dark.png differ diff --git a/docs/public/vitest-ui-show-coverage-light.png b/docs/public/vitest-ui-show-coverage-light.png new file mode 100644 index 000000000000..b4ef044333ed Binary files /dev/null and b/docs/public/vitest-ui-show-coverage-light.png differ diff --git a/packages/browser/src/client/main.ts b/packages/browser/src/client/main.ts index 25c91f157f5a..9dac5f0c3aa7 100644 --- a/packages/browser/src/client/main.ts +++ b/packages/browser/src/client/main.ts @@ -1,5 +1,4 @@ import { createClient } from '@vitest/ws-client' -// eslint-disable-next-line no-restricted-imports import type { ResolvedConfig } from 'vitest' import type { CancelReason, VitestRunner } from '@vitest/runner' import { createBrowserRunner } from './runner' diff --git a/packages/coverage-c8/src/provider.ts b/packages/coverage-c8/src/provider.ts index 55d7c4a0dbfe..28e922c95747 100644 --- a/packages/coverage-c8/src/provider.ts +++ b/packages/coverage-c8/src/provider.ts @@ -9,7 +9,6 @@ import { provider } from 'std-env' import type { EncodedSourceMap } from 'vite-node' import { coverageConfigDefaults } from 'vitest/config' import { BaseCoverageProvider } from 'vitest/coverage' -// eslint-disable-next-line no-restricted-imports import type { AfterSuiteRunMeta, CoverageC8Options, CoverageProvider, ReportContext, ResolvedCoverageOptions } from 'vitest' import type { Vitest } from 'vitest/node' import type { Report } from 'c8' diff --git a/packages/coverage-istanbul/src/provider.ts b/packages/coverage-istanbul/src/provider.ts index c932c01aaa4d..e10f0ca91a11 100644 --- a/packages/coverage-istanbul/src/provider.ts +++ b/packages/coverage-istanbul/src/provider.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-restricted-imports */ import { existsSync, promises as fs } from 'node:fs' import { relative, resolve } from 'pathe' import type { TransformPluginContext } from 'rollup' diff --git a/packages/ui/client/components.d.ts b/packages/ui/client/components.d.ts index 503d2d527825..e6aac78b46e0 100644 --- a/packages/ui/client/components.d.ts +++ b/packages/ui/client/components.d.ts @@ -11,6 +11,7 @@ declare module '@vue/runtime-core' { export interface GlobalComponents { CodeMirror: typeof import('./components/CodeMirror.vue')['default'] ConnectionOverlay: typeof import('./components/ConnectionOverlay.vue')['default'] + Coverage: typeof import('./components/Coverage.vue')['default'] Dashboard: typeof import('./components/Dashboard.vue')['default'] DashboardEntry: typeof import('./components/dashboard/DashboardEntry.vue')['default'] DetailsPanel: typeof import('./components/DetailsPanel.vue')['default'] diff --git a/packages/ui/client/components/Coverage.vue b/packages/ui/client/components/Coverage.vue new file mode 100644 index 000000000000..6ddad3d5a0b0 --- /dev/null +++ b/packages/ui/client/components/Coverage.vue @@ -0,0 +1,40 @@ + + + + + + + Coverage + + + + + + + + diff --git a/packages/ui/client/components/Navigation.vue b/packages/ui/client/components/Navigation.vue index 84984d99d0a0..af8f19edc9f0 100644 --- a/packages/ui/client/components/Navigation.vue +++ b/packages/ui/client/components/Navigation.vue @@ -1,8 +1,18 @@ - + Vitest + + + + + + Coverage enabled but missing html reporter. + + Add html reporter to your configuration to see coverage here. + + + + + diff --git a/packages/ui/client/components/Suites.vue b/packages/ui/client/components/Suites.vue index 72b47c092d52..492b10d3bb3e 100644 --- a/packages/ui/client/components/Suites.vue +++ b/packages/ui/client/components/Suites.vue @@ -1,5 +1,6 @@ @@ -27,7 +35,7 @@ function updateSnapshot() { v-if="!isReport" v-tooltip.bottom="'Rerun file'" icon="i-carbon-play" - @click="runCurrent()" + @click="onRunCurrent()" /> diff --git a/packages/ui/client/composables/navigation.ts b/packages/ui/client/composables/navigation.ts index 32821dda5d4b..cb6fd3186cfc 100644 --- a/packages/ui/client/composables/navigation.ts +++ b/packages/ui/client/composables/navigation.ts @@ -1,10 +1,34 @@ -import { client, findById } from './client' +import { client, config, findById, testRunState } from './client' import { activeFileId } from './params' import type { File } from '#types' export const currentModule = ref() export const dashboardVisible = ref(true) +export const coverageVisible = ref(false) +export const disableCoverage = ref(true) +export const coverage = computed(() => config.value?.coverage) +export const coverageConfigured = computed(() => { + if (!config.value?.api?.port) + return false + return coverage.value?.enabled +}) +export const coverageEnabled = computed(() => { + return coverageConfigured.value + && coverage.value.reporter.map(([reporterName]) => reporterName).includes('html') +}) +export const coverageUrl = computed(() => { + if (coverageEnabled.value) { + const url = `${window.location.protocol}//${window.location.hostname}:${config.value!.api!.port!}` + const idx = coverage.value!.reportsDirectory.lastIndexOf('/') + return `${url}/${coverage.value!.reportsDirectory.slice(idx + 1)}/index.html` + } + + return undefined +}) +watch(testRunState, (state) => { + disableCoverage.value = state === 'running' +}, { immediate: true }) export function initializeNavigation() { const file = activeFileId.value if (file && file.length > 0) { @@ -12,6 +36,7 @@ export function initializeNavigation() { if (current) { currentModule.value = current dashboardVisible.value = false + coverageVisible.value = false } else { watchOnce( @@ -19,6 +44,7 @@ export function initializeNavigation() { () => { currentModule.value = findById(file) dashboardVisible.value = false + coverageVisible.value = false }, ) } @@ -29,8 +55,16 @@ export function initializeNavigation() { export function showDashboard(show: boolean) { dashboardVisible.value = show + coverageVisible.value = false if (show) { currentModule.value = undefined activeFileId.value = '' } } + +export function showCoverage() { + coverageVisible.value = true + dashboardVisible.value = false + currentModule.value = undefined + activeFileId.value = '' +} diff --git a/packages/ui/client/pages/index.vue b/packages/ui/client/pages/index.vue index 5ee79edf0b4c..f92e9d63dc5b 100644 --- a/packages/ui/client/pages/index.vue +++ b/packages/ui/client/pages/index.vue @@ -1,7 +1,7 @@