Skip to content

Commit 3946d7b

Browse files
MyesteryAustinMroz
andauthored
Road to no explicit any part 8 group 5 (#8329)
## Summary - Add `createMockLLink` and `createMockLinks` factory functions to handle hybrid Map/Record types - Replace `as any` assertions with type-safe factory functions in minimap tests - Implement proper Pinia store mocking using `vi.hoisted()` pattern - Remove unused `createMockSubgraph` export (shadowed by local implementations) ## Test plan - [x] All minimap tests pass (29 tests) - [x] `pnpm typecheck` passes - [x] `pnpm lint` passes - [x] `pnpm knip` passes ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8329-Road-to-no-explicit-any-part-8-group-5-2f56d73d365081218882de81d5526220) by [Unito](https://www.unito.io) --------- Co-authored-by: AustinMroz <austin@comfy.org>
1 parent 440e25e commit 3946d7b

20 files changed

+684
-464
lines changed

src/platform/updates/common/releaseService.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ describe('useReleaseService', () => {
190190
})
191191

192192
it('should set loading state correctly', async () => {
193-
let resolvePromise: (value: any) => void
193+
let resolvePromise: (value: unknown) => void
194194
const promise = new Promise((resolve) => {
195195
resolvePromise = resolve
196196
})

src/platform/updates/common/releaseStore.test.ts

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { createPinia, setActivePinia } from 'pinia'
22
import { compare, valid } from 'semver'
3+
import type { Mock } from 'vitest'
34
import { beforeEach, describe, expect, it, vi } from 'vitest'
5+
import { ref } from 'vue'
46

7+
import type { ReleaseNote } from '@/platform/updates/common/releaseService'
58
import { useReleaseStore } from '@/platform/updates/common/releaseStore'
69

710
// Mock the dependencies
@@ -19,9 +22,25 @@ vi.mock('@vueuse/core', () => ({
1922

2023
describe('useReleaseStore', () => {
2124
let store: ReturnType<typeof useReleaseStore>
22-
let mockReleaseService: any
23-
let mockSettingStore: any
24-
let mockSystemStatsStore: any
25+
let mockReleaseService: {
26+
getReleases: Mock
27+
isLoading: ReturnType<typeof ref<boolean>>
28+
error: ReturnType<typeof ref<string | null>>
29+
}
30+
let mockSettingStore: { get: Mock; set: Mock }
31+
let mockSystemStatsStore: {
32+
systemStats: {
33+
system: {
34+
comfyui_version: string
35+
argv?: string[]
36+
[key: string]: unknown
37+
}
38+
devices?: unknown[]
39+
} | null
40+
isInitialized: boolean
41+
refetchSystemStats: Mock
42+
getFormFactor: Mock
43+
}
2544

2645
const mockRelease = {
2746
id: 1,
@@ -38,11 +57,11 @@ describe('useReleaseStore', () => {
3857
// Reset all mocks
3958
vi.clearAllMocks()
4059

41-
// Setup mock services
60+
// Setup mock services with proper refs
4261
mockReleaseService = {
4362
getReleases: vi.fn(),
44-
isLoading: { value: false },
45-
error: { value: null }
63+
isLoading: ref(false),
64+
error: ref(null)
4665
}
4766

4867
mockSettingStore = {
@@ -68,9 +87,21 @@ describe('useReleaseStore', () => {
6887
const { useSystemStatsStore } = await import('@/stores/systemStatsStore')
6988
const { isElectron } = await import('@/utils/envUtil')
7089

71-
vi.mocked(useReleaseService).mockReturnValue(mockReleaseService)
72-
vi.mocked(useSettingStore).mockReturnValue(mockSettingStore)
73-
vi.mocked(useSystemStatsStore).mockReturnValue(mockSystemStatsStore)
90+
vi.mocked(useReleaseService).mockReturnValue(
91+
mockReleaseService as Partial<
92+
ReturnType<typeof useReleaseService>
93+
> as ReturnType<typeof useReleaseService>
94+
)
95+
vi.mocked(useSettingStore).mockReturnValue(
96+
mockSettingStore as Partial<
97+
ReturnType<typeof useSettingStore>
98+
> as ReturnType<typeof useSettingStore>
99+
)
100+
vi.mocked(useSystemStatsStore).mockReturnValue(
101+
mockSystemStatsStore as Partial<
102+
ReturnType<typeof useSystemStatsStore>
103+
> as ReturnType<typeof useSystemStatsStore>
104+
)
74105
vi.mocked(isElectron).mockReturnValue(true)
75106
vi.mocked(valid).mockReturnValue('1.0.0')
76107

@@ -171,7 +202,7 @@ describe('useReleaseStore', () => {
171202
})
172203

173204
it('should show popup for latest version', () => {
174-
mockSystemStatsStore.systemStats.system.comfyui_version = '1.2.0'
205+
mockSystemStatsStore.systemStats!.system.comfyui_version = '1.2.0'
175206

176207
vi.mocked(compare).mockReturnValue(0)
177208

@@ -213,7 +244,7 @@ describe('useReleaseStore', () => {
213244
})
214245

215246
it('should not show popup even for latest version', () => {
216-
mockSystemStatsStore.systemStats.system.comfyui_version = '1.2.0'
247+
mockSystemStatsStore.systemStats!.system.comfyui_version = '1.2.0'
217248

218249
vi.mocked(compare).mockReturnValue(0)
219250

@@ -265,7 +296,7 @@ describe('useReleaseStore', () => {
265296
})
266297

267298
it('should skip fetching when --disable-api-nodes is present', async () => {
268-
mockSystemStatsStore.systemStats.system.argv = ['--disable-api-nodes']
299+
mockSystemStatsStore.systemStats!.system.argv = ['--disable-api-nodes']
269300

270301
await store.initialize()
271302

@@ -274,7 +305,7 @@ describe('useReleaseStore', () => {
274305
})
275306

276307
it('should skip fetching when --disable-api-nodes is one of multiple args', async () => {
277-
mockSystemStatsStore.systemStats.system.argv = [
308+
mockSystemStatsStore.systemStats!.system.argv = [
278309
'--port',
279310
'8080',
280311
'--disable-api-nodes',
@@ -288,7 +319,7 @@ describe('useReleaseStore', () => {
288319
})
289320

290321
it('should fetch normally when --disable-api-nodes is not present', async () => {
291-
mockSystemStatsStore.systemStats.system.argv = [
322+
mockSystemStatsStore.systemStats!.system.argv = [
292323
'--port',
293324
'8080',
294325
'--verbose'
@@ -302,7 +333,7 @@ describe('useReleaseStore', () => {
302333
})
303334

304335
it('should fetch normally when argv is undefined', async () => {
305-
mockSystemStatsStore.systemStats.system.argv = undefined
336+
mockSystemStatsStore.systemStats!.system.argv = undefined
306337
mockReleaseService.getReleases.mockResolvedValue([mockRelease])
307338

308339
await store.initialize()
@@ -330,8 +361,8 @@ describe('useReleaseStore', () => {
330361
})
331362

332363
it('should set loading state correctly', async () => {
333-
let resolvePromise: (value: any) => void
334-
const promise = new Promise((resolve) => {
364+
let resolvePromise: (value: ReleaseNote[] | null) => void
365+
const promise = new Promise<ReleaseNote[] | null>((resolve) => {
335366
resolvePromise = resolve
336367
})
337368

@@ -372,7 +403,7 @@ describe('useReleaseStore', () => {
372403

373404
describe('--disable-api-nodes argument handling', () => {
374405
it('should skip fetchReleases when --disable-api-nodes is present', async () => {
375-
mockSystemStatsStore.systemStats.system.argv = ['--disable-api-nodes']
406+
mockSystemStatsStore.systemStats!.system.argv = ['--disable-api-nodes']
376407

377408
await store.fetchReleases()
378409

@@ -381,7 +412,7 @@ describe('useReleaseStore', () => {
381412
})
382413

383414
it('should skip fetchReleases when --disable-api-nodes is among other args', async () => {
384-
mockSystemStatsStore.systemStats.system.argv = [
415+
mockSystemStatsStore.systemStats!.system.argv = [
385416
'--port',
386417
'8080',
387418
'--disable-api-nodes',
@@ -395,7 +426,7 @@ describe('useReleaseStore', () => {
395426
})
396427

397428
it('should proceed with fetchReleases when --disable-api-nodes is not present', async () => {
398-
mockSystemStatsStore.systemStats.system.argv = [
429+
mockSystemStatsStore.systemStats!.system.argv = [
399430
'--port',
400431
'8080',
401432
'--verbose'
@@ -407,8 +438,8 @@ describe('useReleaseStore', () => {
407438
expect(mockReleaseService.getReleases).toHaveBeenCalled()
408439
})
409440

410-
it('should proceed with fetchReleases when argv is null', async () => {
411-
mockSystemStatsStore.systemStats.system.argv = null
441+
it('should proceed with fetchReleases when argv is undefined', async () => {
442+
mockSystemStatsStore.systemStats!.system.argv = undefined
412443
mockReleaseService.getReleases.mockResolvedValue([mockRelease])
413444

414445
await store.fetchReleases()
@@ -515,7 +546,7 @@ describe('useReleaseStore', () => {
515546
})
516547

517548
it('should show popup for latest version', () => {
518-
mockSystemStatsStore.systemStats.system.comfyui_version = '1.2.0' // Same as release
549+
mockSystemStatsStore.systemStats!.system.comfyui_version = '1.2.0' // Same as release
519550
mockSettingStore.get.mockImplementation((key: string) => {
520551
if (key === 'Comfy.Notification.ShowVersionUpdates') return true
521552
return null
@@ -592,7 +623,7 @@ describe('useReleaseStore', () => {
592623
})
593624

594625
it('should show popup for latest version', () => {
595-
mockSystemStatsStore.systemStats.system.comfyui_version = '1.2.0'
626+
mockSystemStatsStore.systemStats!.system.comfyui_version = '1.2.0'
596627

597628
vi.mocked(compare).mockReturnValue(0)
598629

@@ -649,7 +680,7 @@ describe('useReleaseStore', () => {
649680
})
650681

651682
it('should NOT show popup even for latest version', () => {
652-
mockSystemStatsStore.systemStats.system.comfyui_version = '1.2.0'
683+
mockSystemStatsStore.systemStats!.system.comfyui_version = '1.2.0'
653684

654685
vi.mocked(compare).mockReturnValue(0)
655686

src/platform/updates/common/useFrontendVersionMismatchWarning.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,20 @@ vi.mock('@/scripts/api', () => ({
4040
// Mock vue-i18n
4141
vi.mock('vue-i18n', () => ({
4242
useI18n: () => ({
43-
t: (key: string, params?: any) => {
43+
t: (key: string, params?: Record<string, string | number> | unknown) => {
4444
if (key === 'g.versionMismatchWarning')
4545
return 'Version Compatibility Warning'
4646
if (key === 'g.versionMismatchWarningMessage' && params) {
47-
return `${params.warning}: ${params.detail} Visit https://docs.comfy.org/installation/update_comfyui#common-update-issues for update instructions.`
47+
const p = params as Record<string, string>
48+
return `${p.warning}: ${p.detail} Visit https://docs.comfy.org/installation/update_comfyui#common-update-issues for update instructions.`
4849
}
4950
if (key === 'g.frontendOutdated' && params) {
50-
return `Frontend version ${params.frontendVersion} is outdated. Backend requires ${params.requiredVersion} or higher.`
51+
const p = params as Record<string, string>
52+
return `Frontend version ${p.frontendVersion} is outdated. Backend requires ${p.requiredVersion} or higher.`
5153
}
5254
if (key === 'g.frontendNewer' && params) {
53-
return `Frontend version ${params.frontendVersion} may not be compatible with backend version ${params.backendVersion}.`
55+
const p = params as Record<string, string>
56+
return `Frontend version ${p.frontendVersion} may not be compatible with backend version ${p.backendVersion}.`
5457
}
5558
return key
5659
}

src/platform/updates/common/versionCompatibilityStore.test.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,21 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
33
import { ref } from 'vue'
44

55
import { useVersionCompatibilityStore } from '@/platform/updates/common/versionCompatibilityStore'
6-
import { useSettingStore } from '@/platform/settings/settingStore'
7-
import { useSystemStatsStore } from '@/stores/systemStatsStore'
86

97
vi.mock('@/config', () => ({
108
default: {
119
app_version: '1.24.0'
1210
}
1311
}))
1412

15-
vi.mock('@/stores/systemStatsStore')
13+
const mockUseSystemStatsStore = vi.hoisted(() => vi.fn())
14+
vi.mock('@/stores/systemStatsStore', () => ({
15+
useSystemStatsStore: mockUseSystemStatsStore
16+
}))
1617

17-
// Mock settingStore
18+
const mockUseSettingStore = vi.hoisted(() => vi.fn())
1819
vi.mock('@/platform/settings/settingStore', () => ({
19-
useSettingStore: vi.fn(() => ({
20-
get: vi.fn(() => false) // Default to warnings enabled (false = not disabled)
21-
}))
20+
useSettingStore: mockUseSettingStore
2221
}))
2322

2423
// Mock useStorage and until from VueUse
@@ -28,10 +27,16 @@ vi.mock('@vueuse/core', () => ({
2827
until: vi.fn(() => Promise.resolve())
2928
}))
3029

30+
type MockSystemStatsStore = {
31+
systemStats: unknown
32+
isInitialized: boolean
33+
refetchSystemStats: ReturnType<typeof vi.fn>
34+
}
35+
3136
describe('useVersionCompatibilityStore', () => {
3237
let store: ReturnType<typeof useVersionCompatibilityStore>
33-
let mockSystemStatsStore: any
34-
let mockSettingStore: any
38+
let mockSystemStatsStore: MockSystemStatsStore
39+
let mockSettingStore: { get: ReturnType<typeof vi.fn> }
3540

3641
beforeEach(() => {
3742
setActivePinia(createPinia())
@@ -49,8 +54,8 @@ describe('useVersionCompatibilityStore', () => {
4954
get: vi.fn(() => false) // Default to warnings enabled
5055
}
5156

52-
vi.mocked(useSystemStatsStore).mockReturnValue(mockSystemStatsStore)
53-
vi.mocked(useSettingStore).mockReturnValue(mockSettingStore)
57+
mockUseSystemStatsStore.mockReturnValue(mockSystemStatsStore)
58+
mockUseSettingStore.mockReturnValue(mockSettingStore)
5459

5560
store = useVersionCompatibilityStore()
5661
})
@@ -213,7 +218,9 @@ describe('useVersionCompatibilityStore', () => {
213218

214219
it('should not show warning when disabled via setting', async () => {
215220
// Enable the disable setting
216-
mockSettingStore.get.mockReturnValue(true)
221+
;(
222+
mockSettingStore as { get: ReturnType<typeof vi.fn> }
223+
).get.mockReturnValue(true)
217224

218225
// Set up version mismatch that would normally show warning
219226
mockSystemStatsStore.systemStats = {
@@ -227,9 +234,9 @@ describe('useVersionCompatibilityStore', () => {
227234
await store.checkVersionCompatibility()
228235

229236
expect(store.shouldShowWarning).toBe(false)
230-
expect(mockSettingStore.get).toHaveBeenCalledWith(
231-
'Comfy.VersionCompatibility.DisableWarnings'
232-
)
237+
expect(
238+
(mockSettingStore as { get: ReturnType<typeof vi.fn> }).get
239+
).toHaveBeenCalledWith('Comfy.VersionCompatibility.DisableWarnings')
233240
})
234241
})
235242

src/platform/updates/components/ReleaseNotificationToast.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
55
import type { ReleaseNote } from '../common/releaseService'
66
import ReleaseNotificationToast from './ReleaseNotificationToast.vue'
77

8+
interface TestWindow extends Window {
9+
electronAPI?: Record<string, unknown>
10+
}
11+
812
const { commandExecuteMock } = vi.hoisted(() => ({
913
commandExecuteMock: vi.fn()
1014
}))
@@ -192,7 +196,7 @@ describe('ReleaseNotificationToast', () => {
192196
value: mockWindowOpen,
193197
writable: true
194198
})
195-
;(window as any).electronAPI = {}
199+
;(window as TestWindow).electronAPI = {}
196200

197201
wrapper = mountComponent()
198202
await wrapper.vm.handleUpdate()
@@ -203,7 +207,7 @@ describe('ReleaseNotificationToast', () => {
203207
expect(mockWindowOpen).not.toHaveBeenCalled()
204208
expect(toastErrorHandlerMock).not.toHaveBeenCalled()
205209

206-
delete (window as any).electronAPI
210+
delete (window as TestWindow).electronAPI
207211
})
208212

209213
it('shows an error toast if the desktop updater flow fails in Electron', async () => {
@@ -220,15 +224,15 @@ describe('ReleaseNotificationToast', () => {
220224
value: mockWindowOpen,
221225
writable: true
222226
})
223-
;(window as any).electronAPI = {}
227+
;(window as TestWindow).electronAPI = {}
224228

225229
wrapper = mountComponent()
226230
await wrapper.vm.handleUpdate()
227231

228232
expect(toastErrorHandlerMock).toHaveBeenCalledWith(error)
229233
expect(mockWindowOpen).not.toHaveBeenCalled()
230234

231-
delete (window as any).electronAPI
235+
delete (window as TestWindow).electronAPI
232236
})
233237

234238
it('calls handleShowChangelog when learn more link is clicked', async () => {

src/platform/updates/components/WhatsNewPopup.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,9 @@ describe('WhatsNewPopup', () => {
165165
wrapper = mountComponent()
166166

167167
// Call the close method directly instead of triggering DOM event
168-
await (wrapper.vm as any).closePopup()
168+
await (
169+
wrapper.vm as typeof wrapper.vm & { closePopup: () => Promise<void> }
170+
).closePopup()
169171

170172
expect(wrapper.emitted('whats-new-dismissed')).toBeTruthy()
171173
})

0 commit comments

Comments
 (0)