use isDesktop

This commit is contained in:
bymyself
2025-12-11 04:15:43 -08:00
parent aab9a30511
commit 91db13909f
28 changed files with 117 additions and 97 deletions

View File

@@ -34,7 +34,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useTerminal } from '@/composables/bottomPanelTabs/useTerminal'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { electronAPI, isDesktop } from '@/utils/envUtil'
import { cn } from '@/utils/tailwindUtil'
const { t } = useI18n()
@@ -84,7 +84,7 @@ const showContextMenu = (event: MouseEvent) => {
electronAPI()?.showContextMenu({ type: 'text' })
}
if (isElectron()) {
if (isDesktop) {
useEventListener(terminalEl, 'contextmenu', showContextMenu)
}

View File

@@ -4,11 +4,11 @@ import {
createWebHistory
} from 'vue-router'
import { isElectron } from '@/utils/envUtil'
import { isDesktop } from '@/utils/envUtil'
import LayoutDefault from '@/views/layouts/LayoutDefault.vue'
const isFileProtocol = window.location.protocol === 'file:'
const basePath = isElectron() ? '/' : window.location.pathname
const basePath = isDesktop ? '/' : window.location.pathname
const router = createRouter({
history: isFileProtocol ? createWebHashHistory() : createWebHistory(basePath),

View File

@@ -1,6 +1,6 @@
import type { ElectronAPI } from '@comfyorg/comfyui-electron-types'
export function isElectron() {
function isElectron() {
return 'electronAPI' in window && window.electronAPI !== undefined
}
@@ -9,5 +9,8 @@ export function electronAPI() {
}
export function isNativeWindow() {
return isElectron() && !!window.navigator.windowControlsOverlay?.visible
return isDesktop && !!window.navigator.windowControlsOverlay?.visible
}
/** Distribution type check - desktop-ui always runs in desktop context */
export const isDesktop = isElectron()

View File

@@ -27,7 +27,7 @@ import { computed, nextTick, onMounted, ref } from 'vue'
import LanguageSelector from '@/components/common/LanguageSelector.vue'
import { electronAPI, isElectron, isNativeWindow } from '../../utils/envUtil'
import { electronAPI, isDesktop, isNativeWindow } from '../../utils/envUtil'
const { dark = false, hideLanguageSelector = false } = defineProps<{
dark?: boolean
@@ -49,7 +49,7 @@ const lightTheme = {
const topMenuRef = ref<HTMLDivElement | null>(null)
onMounted(async () => {
if (isElectron()) {
if (isDesktop) {
await nextTick()
electronAPI().changeTheme({

View File

@@ -75,16 +75,15 @@ import CurrentUserButton from '@/components/topbar/CurrentUserButton.vue'
import LoginButton from '@/components/topbar/LoginButton.vue'
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
import { isDesktop } from '@/platform/distribution/types'
import { app } from '@/scripts/app'
import { useQueueStore } from '@/stores/queueStore'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { isElectron } from '@/utils/envUtil'
const workspaceStore = useWorkspaceStore()
const rightSidePanelStore = useRightSidePanelStore()
const { isLoggedIn } = useCurrentUser()
const isDesktop = isElectron()
const { t } = useI18n()
const isQueueOverlayExpanded = ref(false)
const queueStore = useQueueStore()

View File

@@ -34,7 +34,8 @@ import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useTerminal } from '@/composables/bottomPanelTabs/useTerminal'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { isDesktop } from '@/platform/distribution/types'
import { electronAPI } from '@/utils/envUtil'
import { cn } from '@/utils/tailwindUtil'
const { t } = useI18n()
@@ -84,7 +85,7 @@ const showContextMenu = (event: MouseEvent) => {
electronAPI()?.showContextMenu({ type: 'text' })
}
if (isElectron()) {
if (isDesktop) {
useEventListener(terminalEl, 'contextmenu', showContextMenu)
}

View File

@@ -13,7 +13,7 @@
</div>
<ListBox :options="missingModels" class="comfy-missing-models">
<template #option="{ option }">
<Suspense v-if="isElectron()">
<Suspense v-if="isDesktop">
<ElectronFileDownload
:url="option.url"
:label="option.label"
@@ -39,8 +39,8 @@ import { useI18n } from 'vue-i18n'
import ElectronFileDownload from '@/components/common/ElectronFileDownload.vue'
import FileDownload from '@/components/common/FileDownload.vue'
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
import { isDesktop } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { isElectron } from '@/utils/envUtil'
// TODO: Read this from server internal API rather than hardcoding here
// as some installations may wish to use custom sources

View File

@@ -158,13 +158,13 @@ import { useI18n } from 'vue-i18n'
import PuzzleIcon from '@/components/icons/PuzzleIcon.vue'
import { useExternalLink } from '@/composables/useExternalLink'
import { isCloud } from '@/platform/distribution/types'
import { isCloud, isDesktop } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useTelemetry } from '@/platform/telemetry'
import type { ReleaseNote } from '@/platform/updates/common/releaseService'
import { useReleaseStore } from '@/platform/updates/common/releaseStore'
import { useCommandStore } from '@/stores/commandStore'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { electronAPI } from '@/utils/envUtil'
import { formatVersionAnchor } from '@/utils/formatUtil'
import { useConflictAcknowledgment } from '@/workbench/extensions/manager/composables/useConflictAcknowledgment'
import { useManagerState } from '@/workbench/extensions/manager/composables/useManagerState'
@@ -237,7 +237,7 @@ const moreItems = computed<MenuItem[]>(() => {
key: 'desktop-guide',
type: 'item',
label: t('helpCenter.desktopUserGuide'),
visible: isElectron(),
visible: isDesktop,
action: () => {
trackResourceClick('docs', true)
openExternalLink(
@@ -253,7 +253,7 @@ const moreItems = computed<MenuItem[]>(() => {
key: 'dev-tools',
type: 'item',
label: t('helpCenter.openDevTools'),
visible: isElectron(),
visible: isDesktop,
action: () => {
openDevTools()
emit('close')
@@ -262,13 +262,13 @@ const moreItems = computed<MenuItem[]>(() => {
{
key: 'divider-1',
type: 'divider',
visible: isElectron()
visible: isDesktop
},
{
key: 'reinstall',
type: 'item',
label: t('helpCenter.reinstall'),
visible: isElectron(),
visible: isDesktop,
action: () => {
onReinstall()
emit('close')
@@ -534,13 +534,13 @@ const onSubmenuLeave = (): void => {
}
const openDevTools = (): void => {
if (isElectron()) {
if (isDesktop) {
electronAPI().openDevTools()
}
}
const onReinstall = (): void => {
if (isElectron()) {
if (isDesktop) {
void electronAPI().reinstall()
}
}

View File

@@ -27,7 +27,7 @@
</div>
</template>
<template #body>
<ElectronDownloadItems v-if="isElectron()" />
<ElectronDownloadItems v-if="isDesktop" />
<Divider type="dashed" class="m-2" />
<TreeExplorer
@@ -55,13 +55,13 @@ import SidebarTabTemplate from '@/components/sidebar/tabs/SidebarTabTemplate.vue
import ElectronDownloadItems from '@/components/sidebar/tabs/modelLibrary/ElectronDownloadItems.vue'
import ModelTreeLeaf from '@/components/sidebar/tabs/modelLibrary/ModelTreeLeaf.vue'
import { useTreeExpansion } from '@/composables/useTreeExpansion'
import { isDesktop } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useLitegraphService } from '@/services/litegraphService'
import type { ComfyModelDef, ModelFolder } from '@/stores/modelStore'
import { ResourceState, useModelStore } from '@/stores/modelStore'
import { useModelToNodeStore } from '@/stores/modelToNodeStore'
import type { TreeExplorerNode, TreeNode } from '@/types/treeExplorerTypes'
import { isElectron } from '@/utils/envUtil'
import { buildTree } from '@/utils/treeUtil'
const modelStore = useModelStore()

View File

@@ -79,6 +79,7 @@ import { useI18n } from 'vue-i18n'
import WorkflowTab from '@/components/topbar/WorkflowTab.vue'
import { useOverflowObserver } from '@/composables/element/useOverflowObserver'
import { isDesktop } from '@/platform/distribution/types'
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
import type { ComfyWorkflow } from '@/platform/workflow/management/stores/workflowStore'
import {
@@ -87,7 +88,6 @@ import {
} from '@/platform/workflow/management/stores/workflowStore'
import { useCommandStore } from '@/stores/commandStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { isElectron } from '@/utils/envUtil'
import { whileMouseDown } from '@/utils/mouseDownUtil'
import WorkflowOverflowMenu from './WorkflowOverflowMenu.vue'
@@ -114,8 +114,6 @@ const showOverflowArrows = ref(false)
const leftArrowEnabled = ref(false)
const rightArrowEnabled = ref(false)
const isDesktop = isElectron()
const workflowToOption = (workflow: ComfyWorkflow): WorkflowOption => ({
value: workflow.path,
workflow

View File

@@ -3,7 +3,7 @@ import { markRaw } from 'vue'
import ModelLibrarySidebarTab from '@/components/sidebar/tabs/ModelLibrarySidebarTab.vue'
import { useElectronDownloadStore } from '@/stores/electronDownloadStore'
import type { SidebarTabExtension } from '@/types/extensionTypes'
import { isElectron } from '@/utils/envUtil'
import { isDesktop } from '@/platform/distribution/types'
export const useModelLibrarySidebarTab = (): SidebarTabExtension => {
return {
@@ -15,7 +15,7 @@ export const useModelLibrarySidebarTab = (): SidebarTabExtension => {
component: markRaw(ModelLibrarySidebarTab),
type: 'vue',
iconBadge: () => {
if (isElectron()) {
if (isDesktop) {
const electronDownloadStore = useElectronDownloadStore()
if (electronDownloadStore.inProgressDownloads.length > 0) {
return electronDownloadStore.inProgressDownloads.length.toString()

View File

@@ -1,6 +1,7 @@
import { computed } from 'vue'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { isDesktop } from '@/platform/distribution/types'
import { electronAPI } from '@/utils/envUtil'
import { i18n } from '@/i18n'
/**
@@ -30,7 +31,7 @@ export function useExternalLink() {
})
const platform = computed(() => {
if (!isElectron()) {
if (!isDesktop) {
return null
}

View File

@@ -8,9 +8,10 @@ import { useWorkflowStore } from '@/platform/workflow/management/stores/workflow
import { app } from '@/scripts/app'
import { useDialogService } from '@/services/dialogService'
import { checkMirrorReachable } from '@/utils/electronMirrorCheck'
import { electronAPI as getElectronAPI, isElectron } from '@/utils/envUtil'
import { isDesktop } from '@/platform/distribution/types'
import { electronAPI as getElectronAPI } from '@/utils/envUtil'
;(async () => {
if (!isElectron()) return
if (!isDesktop) return
const electronAPI = getElectronAPI()
const desktopAppVersion = await electronAPI.getElectronVersion()

View File

@@ -4,11 +4,10 @@ import { useI18n } from 'vue-i18n'
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import { isCloud } from '@/platform/distribution/types'
import { isCloud, isDesktop } from '@/platform/distribution/types'
import type { SettingTreeNode } from '@/platform/settings/settingStore'
import { useSettingStore } from '@/platform/settings/settingStore'
import type { SettingParams } from '@/platform/settings/types'
import { isElectron } from '@/utils/envUtil'
import { normalizeI18nKey } from '@/utils/formatUtil'
import { buildTree } from '@/utils/treeUtil'
import { useVueFeatureFlags } from '@/composables/useVueFeatureFlags'
@@ -161,7 +160,7 @@ export function useSettingUI(
userPanel,
keybindingPanel,
extensionPanel,
...(isElectron() ? [serverConfigPanel] : []),
...(isDesktop ? [serverConfigPanel] : []),
...(shouldShowPlanCreditsPanel.value && subscriptionPanel
? [subscriptionPanel]
: [])
@@ -221,7 +220,7 @@ export function useSettingUI(
keybindingPanel.node,
extensionPanel.node,
aboutPanel.node,
...(isElectron() ? [serverConfigPanel.node] : [])
...(isDesktop ? [serverConfigPanel.node] : [])
].map(translateCategory)
}
])

View File

@@ -3,10 +3,9 @@ import { defineStore } from 'pinia'
import { compare, valid } from 'semver'
import { computed, ref } from 'vue'
import { isCloud } from '@/platform/distribution/types'
import { isCloud, isDesktop } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useSystemStatsStore } from '@/stores/systemStatsStore'
import { isElectron } from '@/utils/envUtil'
import { stringToLocale } from '@/utils/formatUtil'
import { useReleaseService } from './releaseService'
@@ -95,7 +94,7 @@ export const useReleaseStore = defineStore('release', () => {
// Show toast if needed
const shouldShowToast = computed(() => {
// Only show on desktop version
if (!isElectron() || isCloud) {
if (!isDesktop || isCloud) {
return false
}
@@ -127,7 +126,7 @@ export const useReleaseStore = defineStore('release', () => {
// Show red-dot indicator
const shouldShowRedDot = computed(() => {
// Only show on desktop version
if (!isElectron() || isCloud) {
if (!isDesktop || isCloud) {
return false
}
@@ -172,7 +171,7 @@ export const useReleaseStore = defineStore('release', () => {
})
const shouldShowPopup = computed(() => {
if (!isElectron() && !isCloud) {
if (!isDesktop && !isCloud) {
return false
}

View File

@@ -2,9 +2,9 @@ import { defineStore } from 'pinia'
import { computed } from 'vue'
import { useExternalLink } from '@/composables/useExternalLink'
import { isCloud } from '@/platform/distribution/types'
import { isCloud, isDesktop } from '@/platform/distribution/types'
import type { AboutPageBadge } from '@/types/comfy'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { electronAPI } from '@/utils/envUtil'
import { formatCommitHash } from '@/utils/formatUtil'
import { useExtensionStore } from './extensionStore'
@@ -24,7 +24,7 @@ export const useAboutPanelStore = defineStore('aboutPanel', () => {
// so the python server's API doesn't have the version info.
{
label: `ComfyUI ${
isElectron()
isDesktop
? 'v' + electronAPI().getComfyUIVersion()
: formatCommitHash(coreVersion.value)
}`,

View File

@@ -3,7 +3,8 @@ import type { DownloadState } from '@comfyorg/comfyui-electron-types'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { isDesktop } from '@/platform/distribution/types'
import { electronAPI } from '@/utils/envUtil'
export interface ElectronDownload extends Pick<
DownloadState,
@@ -23,7 +24,7 @@ export const useElectronDownloadStore = defineStore('downloads', () => {
downloads.value.find((download) => url === download.url)
const initialize = async () => {
if (isElectron()) {
if (isDesktop) {
const allDownloads = await DownloadManager.getAllDownloads()
for (const download of allDownloads) {

View File

@@ -1,10 +1,9 @@
import { useAsyncState } from '@vueuse/core'
import { defineStore } from 'pinia'
import { isCloud } from '@/platform/distribution/types'
import { isCloud, isDesktop } from '@/platform/distribution/types'
import type { SystemStats } from '@/schemas/apiSchema'
import { api } from '@/scripts/api'
import { isElectron } from '@/utils/envUtil'
export const useSystemStatsStore = defineStore('systemStats', () => {
const fetchSystemStatsData = async () => {
@@ -40,7 +39,6 @@ export const useSystemStatsStore = defineStore('systemStats', () => {
}
const os = systemStats.value.system.os.toLowerCase()
const isDesktop = isElectron()
if (isDesktop) {
if (os.includes('windows')) {

View File

@@ -9,7 +9,7 @@ import {
import { useCommandStore } from '@/stores/commandStore'
import type { ComfyExtension } from '@/types/comfy'
import type { BottomPanelExtension } from '@/types/extensionTypes'
import { isElectron } from '@/utils/envUtil'
import { isDesktop } from '@/platform/distribution/types'
type PanelType = 'terminal' | 'shortcuts'
@@ -123,7 +123,7 @@ export const useBottomPanelStore = defineStore('bottomPanel', () => {
const registerCoreBottomPanelTabs = () => {
registerBottomPanelTab(useLogsTerminalTab())
if (isElectron()) {
if (isDesktop) {
registerBottomPanelTab(useCommandTerminalTab())
}
useShortcutsTab().forEach(registerBottomPanelTab)

View File

@@ -17,7 +17,8 @@
<GlobalToast />
<RerouteMigrationToast />
<UnloadWindowConfirmDialog v-if="!isElectron()" />
<VueNodesMigrationToast />
<UnloadWindowConfirmDialog v-if="!isDesktop" />
<MenuHamburger />
</template>
@@ -49,7 +50,7 @@ import { useErrorHandling } from '@/composables/useErrorHandling'
import { useProgressFavicon } from '@/composables/useProgressFavicon'
import { SERVER_CONFIG_ITEMS } from '@/constants/serverConfig'
import { i18n, loadLocale } from '@/i18n'
import { isCloud } from '@/platform/distribution/types'
import { isCloud, isDesktop } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useTelemetry } from '@/platform/telemetry'
import { useFrontendVersionMismatchWarning } from '@/platform/updates/common/useFrontendVersionMismatchWarning'
@@ -76,7 +77,7 @@ import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { electronAPI } from '@/utils/envUtil'
import LinearView from '@/views/LinearView.vue'
setupAutoQueueHandler()
@@ -111,7 +112,7 @@ watch(
document.body.classList.add(DARK_THEME_CLASS)
}
if (isElectron()) {
if (isDesktop) {
electronAPI().changeTheme({
color: 'rgba(0, 0, 0, 0)',
symbolColor: newTheme.colors.comfy_base['input-text']
@@ -121,7 +122,7 @@ watch(
{ immediate: true }
)
if (isElectron()) {
if (isDesktop) {
watch(
() => queueStore.tasks,
(newTasks, oldTasks) => {

View File

@@ -18,6 +18,7 @@ import {
import { useAssetsSidebarTab } from '@/composables/sidebarTabs/useAssetsSidebarTab'
import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { isDesktop } from '@/platform/distribution/types'
import { useTelemetry } from '@/platform/telemetry'
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
@@ -27,7 +28,6 @@ import { app } from '@/scripts/app'
import { useCommandStore } from '@/stores/commandStore'
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
import { useQueueSettingsStore } from '@/stores/queueStore'
import { isElectron } from '@/utils/envUtil'
const nodeOutputStore = useNodeOutputStore()
const commandStore = useCommandStore()
@@ -60,7 +60,6 @@ const nodeDatas = computed(() => {
.map(nodeToNodeData)
})
const { isLoggedIn } = useCurrentUser()
const isDesktop = isElectron()
const batchCountWidget = {
options: { step2: 1, precision: 1, min: 1, max: 100 },

View File

@@ -22,7 +22,8 @@
<script setup lang="ts">
import { nextTick, onMounted, ref } from 'vue'
import { electronAPI, isElectron, isNativeWindow } from '@/utils/envUtil'
import { isDesktop } from '@/platform/distribution/types'
import { electronAPI, isNativeWindow } from '@/utils/envUtil'
const { dark = false } = defineProps<{
dark?: boolean
@@ -40,7 +41,7 @@ const lightTheme = {
const topMenuRef = ref<HTMLDivElement | null>(null)
onMounted(async () => {
if (isElectron()) {
if (isDesktop) {
await nextTick()
electronAPI().changeTheme({

View File

@@ -7,9 +7,8 @@ import { createI18n } from 'vue-i18n'
import TopMenuSection from '@/components/TopMenuSection.vue'
import CurrentUserButton from '@/components/topbar/CurrentUserButton.vue'
import LoginButton from '@/components/topbar/LoginButton.vue'
import { isElectron } from '@/utils/envUtil'
const mockData = vi.hoisted(() => ({ isLoggedIn: false }))
const mockData = vi.hoisted(() => ({ isLoggedIn: false, isDesktop: false }))
vi.mock('@/composables/auth/useCurrentUser', () => ({
useCurrentUser: () => {
@@ -19,7 +18,12 @@ vi.mock('@/composables/auth/useCurrentUser', () => ({
}
}))
vi.mock('@/utils/envUtil')
vi.mock('@/platform/distribution/types', () => ({
isCloud: false,
get isDesktop() {
return mockData.isDesktop
}
}))
vi.mock('@/stores/firebaseAuthStore', () => ({
useFirebaseAuthStore: vi.fn(() => ({
currentUser: null,
@@ -62,6 +66,8 @@ function createWrapper() {
describe('TopMenuSection', () => {
beforeEach(() => {
vi.resetAllMocks()
mockData.isDesktop = false
mockData.isLoggedIn = false
})
describe('authentication state', () => {
@@ -84,7 +90,7 @@ describe('TopMenuSection', () => {
describe('on desktop platform', () => {
it('should display LoginButton and not display CurrentUserButton', () => {
vi.mocked(isElectron).mockReturnValue(true)
mockData.isDesktop = true
const wrapper = createWrapper()
expect(wrapper.findComponent(LoginButton).exists()).toBe(true)
expect(wrapper.findComponent(CurrentUserButton).exists()).toBe(false)

View File

@@ -53,8 +53,11 @@ vi.mock('@/composables/bottomPanelTabs/useTerminal', () => ({
}))
}))
vi.mock('@/platform/distribution/types', () => ({
isDesktop: false
}))
vi.mock('@/utils/envUtil', () => ({
isElectron: vi.fn(() => false),
electronAPI: vi.fn(() => null)
}))

View File

@@ -1,8 +1,15 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
// Mock the distribution types
const mockData = vi.hoisted(() => ({ isDesktop: false }))
vi.mock('@/platform/distribution/types', () => ({
get isDesktop() {
return mockData.isDesktop
}
}))
// Mock the environment utilities
vi.mock('@/utils/envUtil', () => ({
isElectron: vi.fn(),
electronAPI: vi.fn()
}))
@@ -20,14 +27,14 @@ vi.mock('@/i18n', () => ({
// Import after mocking to get the mocked versions
import { useExternalLink } from '@/composables/useExternalLink'
import { electronAPI, isElectron } from '@/utils/envUtil'
import { electronAPI } from '@/utils/envUtil'
describe('useExternalLink', () => {
beforeEach(() => {
vi.clearAllMocks()
// Reset to default state
i18n.global.locale.value = 'en'
vi.mocked(isElectron).mockReturnValue(false)
mockData.isDesktop = false
})
describe('staticUrls', () => {
@@ -95,7 +102,7 @@ describe('useExternalLink', () => {
it('should add platform suffix when requested', () => {
i18n.global.locale.value = 'en'
vi.mocked(isElectron).mockReturnValue(true)
mockData.isDesktop = true
vi.mocked(electronAPI).mockReturnValue({
getPlatform: () => 'darwin'
} as ReturnType<typeof electronAPI>)
@@ -107,7 +114,7 @@ describe('useExternalLink', () => {
it('should add platform suffix with trailing slash', () => {
i18n.global.locale.value = 'en'
vi.mocked(isElectron).mockReturnValue(true)
mockData.isDesktop = true
vi.mocked(electronAPI).mockReturnValue({
getPlatform: () => 'win32'
} as ReturnType<typeof electronAPI>)
@@ -119,7 +126,7 @@ describe('useExternalLink', () => {
it('should combine locale and platform', () => {
i18n.global.locale.value = 'zh'
vi.mocked(isElectron).mockReturnValue(true)
mockData.isDesktop = true
vi.mocked(electronAPI).mockReturnValue({
getPlatform: () => 'darwin'
} as ReturnType<typeof electronAPI>)
@@ -136,7 +143,7 @@ describe('useExternalLink', () => {
it('should not add platform when not desktop', () => {
i18n.global.locale.value = 'en'
vi.mocked(isElectron).mockReturnValue(false)
mockData.isDesktop = false
const { buildDocsUrl } = useExternalLink()
const url = buildDocsUrl('/installation/desktop', { platform: true })

View File

@@ -47,8 +47,8 @@ vi.mock('@/stores/commandStore', () => ({
})
}))
vi.mock('@/utils/envUtil', () => ({
isElectron: () => false
vi.mock('@/platform/distribution/types', () => ({
isDesktop: false
}))
describe('useBottomPanelStore', () => {

View File

@@ -5,9 +5,14 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { useReleaseStore } from '@/platform/updates/common/releaseStore'
// Mock the dependencies
const mockData = vi.hoisted(() => ({ isDesktop: true }))
vi.mock('semver')
vi.mock('@/utils/envUtil')
vi.mock('@/platform/distribution/types', () => ({ isCloud: false }))
vi.mock('@/platform/distribution/types', () => ({
isCloud: false,
get isDesktop() {
return mockData.isDesktop
}
}))
vi.mock('@/platform/updates/common/releaseService')
vi.mock('@/platform/settings/settingStore')
vi.mock('@/stores/systemStatsStore')
@@ -66,12 +71,11 @@ describe('useReleaseStore', () => {
await import('@/platform/updates/common/releaseService')
const { useSettingStore } = await import('@/platform/settings/settingStore')
const { useSystemStatsStore } = await import('@/stores/systemStatsStore')
const { isElectron } = await import('@/utils/envUtil')
vi.mocked(useReleaseService).mockReturnValue(mockReleaseService)
vi.mocked(useSettingStore).mockReturnValue(mockSettingStore)
vi.mocked(useSystemStatsStore).mockReturnValue(mockSystemStatsStore)
vi.mocked(isElectron).mockReturnValue(true)
mockData.isDesktop = true
vi.mocked(valid).mockReturnValue('1.0.0')
// Default showVersionUpdates to true
@@ -562,7 +566,7 @@ describe('useReleaseStore', () => {
})
})
describe('isElectron environment checks', () => {
describe('isDesktop environment checks', () => {
beforeEach(async () => {
// Set up a new version available
store.releases = [mockRelease]
@@ -572,10 +576,9 @@ describe('useReleaseStore', () => {
})
})
describe('when running in Electron (desktop)', () => {
describe('when running in desktop', () => {
beforeEach(async () => {
const { isElectron } = await import('@/utils/envUtil')
vi.mocked(isElectron).mockReturnValue(true)
mockData.isDesktop = true
})
it('should show toast when conditions are met', () => {
@@ -600,10 +603,9 @@ describe('useReleaseStore', () => {
})
})
describe('when NOT running in Electron (web)', () => {
describe('when NOT running in desktop (web)', () => {
beforeEach(async () => {
const { isElectron } = await import('@/utils/envUtil')
vi.mocked(isElectron).mockReturnValue(false)
mockData.isDesktop = false
})
it('should NOT show toast even when all other conditions are met', () => {

View File

@@ -3,7 +3,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { api } from '@/scripts/api'
import { useSystemStatsStore } from '@/stores/systemStatsStore'
import { isElectron } from '@/utils/envUtil'
// Mock the API
vi.mock('@/scripts/api', () => ({
@@ -12,13 +11,15 @@ vi.mock('@/scripts/api', () => ({
}
}))
// Mock the envUtil
vi.mock('@/utils/envUtil', () => ({
isElectron: vi.fn()
// Mock the distribution types
const mockData = vi.hoisted(() => ({ isDesktop: false }))
vi.mock('@/platform/distribution/types', () => ({
isCloud: false,
get isDesktop() {
return mockData.isDesktop
}
}))
vi.mock('@/platform/distribution/types', () => ({ isCloud: false }))
describe('useSystemStatsStore', () => {
let store: ReturnType<typeof useSystemStatsStore>
@@ -159,9 +160,9 @@ describe('useSystemStatsStore', () => {
expect(store.getFormFactor()).toBe('other')
})
describe('desktop environment (Electron)', () => {
describe('desktop environment', () => {
beforeEach(() => {
vi.mocked(isElectron).mockReturnValue(true)
mockData.isDesktop = true
})
it('should return "desktop-windows" for Windows desktop', () => {
@@ -237,9 +238,9 @@ describe('useSystemStatsStore', () => {
})
})
describe('git environment (non-Electron)', () => {
describe('git environment (non-desktop)', () => {
beforeEach(() => {
vi.mocked(isElectron).mockReturnValue(false)
mockData.isDesktop = false
})
it('should return "git-windows" for Windows git', () => {
@@ -317,7 +318,7 @@ describe('useSystemStatsStore', () => {
describe('case insensitive OS detection', () => {
beforeEach(() => {
vi.mocked(isElectron).mockReturnValue(false)
mockData.isDesktop = false
})
it('should handle uppercase OS names', () => {