198 lines
5.3 KiB
TypeScript

import type { File, Task } from '@vitest/runner'
import type { Params } from './params'
import { useLocalStorage, watchOnce } from '@vueuse/core'
import { computed, reactive, ref, watch } from 'vue'
import { viewport } from './browser'
import { browserState, client, config, findById } from './client'
import { testRunState } from './client/state'
import { showTaskSource } from './codemirror'
import { activeFileId, columnNumber, lineNumber, selectedTest, viewMode } from './params'
export const currentModule = ref<File>()
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(() => coverage.value?.enabled)
export const coverageEnabled = computed(() => {
return (
coverageConfigured.value
&& !!coverage.value.htmlReporter
)
})
export const mainSizes = useLocalStorage<[left: number, right: number]>(
'vitest-ui_splitpanes-mainSizes',
[33, 67],
)
export const detailSizes = useLocalStorage<[left: number, right: number]>(
'vitest-ui_splitpanes-detailSizes',
[
// @ts-expect-error "browserState" is not initialised yet
window.__vitest_browser_runner__?.provider === 'webdriverio'
? ((viewport.value[0] / window.outerWidth) * 100)
: 33,
67,
],
)
// live sizes of panels in percentage
export const panels = reactive({
navigation: mainSizes.value[0],
details: {
size: mainSizes.value[1],
// these sizes are relative to the details panel
browser: detailSizes.value[0],
main: detailSizes.value[1],
},
})
// TODO
// For html report preview, "coverage.reportsDirectory" must be explicitly set as a subdirectory of html report.
// Handling other cases seems difficult, so this limitation is mentioned in the documentation for now.
export const coverageUrl = computed(() => {
if (coverageEnabled.value) {
const idx = coverage.value!.reportsDirectory.lastIndexOf('/')
const htmlReporterSubdir = coverage.value!.htmlReporter?.subdir
return htmlReporterSubdir
? `/${coverage.value!.reportsDirectory.slice(idx + 1)}/${
htmlReporterSubdir
}/index.html`
: `/${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) {
const current = findById(file)
if (current) {
currentModule.value = current
dashboardVisible.value = false
coverageVisible.value = false
}
else {
watchOnce(
() => client.state.getFiles(),
() => {
currentModule.value = findById(file)
dashboardVisible.value = false
coverageVisible.value = false
},
)
}
}
return dashboardVisible
}
export function showDashboard(show: boolean) {
dashboardVisible.value = show
coverageVisible.value = false
if (show) {
currentModule.value = undefined
activeFileId.value = ''
}
}
export function navigateTo({ file, line, view, test, column }: Params) {
activeFileId.value = file
lineNumber.value = line
columnNumber.value = column
viewMode.value = view
selectedTest.value = test
currentModule.value = findById(file)
showDashboard(false)
}
export function clickOnTask(task: Task) {
if (task.type === 'test') {
if (viewMode.value === 'editor') {
showTaskSource(task)
}
else {
navigateTo({
file: task.file.id,
line: null,
column: null,
view: viewMode.value,
test: task.id,
})
}
}
else {
navigateTo({
file: task.file.id,
test: null,
line: null,
view: viewMode.value,
column: null,
})
}
}
export function showCoverage() {
coverageVisible.value = true
dashboardVisible.value = false
currentModule.value = undefined
activeFileId.value = ''
}
export function hideRightPanel() {
panels.details.browser = 100
panels.details.main = 0
detailSizes.value = [100, 0]
}
function calculateBrowserPanel() {
// we don't scale webdriverio provider because it doesn't support scaling
// TODO: find a way to make this universal - maybe show browser separately(?)
if (browserState?.provider === 'webdriverio') {
const parentWindow = window.outerWidth * (panels.details.size / 100)
// 40 is 20px padding for each sice
const tabWidth = ((viewport.value[0] + 20) / parentWindow) * 100
return tabWidth
}
return 33
}
export function showRightPanel() {
panels.details.browser = calculateBrowserPanel()
panels.details.main = 100 - panels.details.browser
detailSizes.value = [
panels.details.browser,
panels.details.main,
]
}
export function showNavigationPanel() {
panels.navigation = 33
panels.details.size = 67
mainSizes.value = [33, 67]
}
export function updateBrowserPanel() {
// we don't need to change the size of the browser panel if the right
// panel is hidden
if (panels.details.main === 0) {
return
}
panels.details.browser = calculateBrowserPanel()
panels.details.main = 100 - panels.details.browser
detailSizes.value = [
panels.details.browser,
panels.details.main,
]
}