diff --git a/eslint.config.ts b/eslint.config.ts index aa59d118c3f..4974637fa6d 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -240,6 +240,20 @@ export default defineConfig([ ] } }, + { + files: ['**/*.test.ts'], + rules: { + 'no-restricted-properties': [ + 'error', + { + object: 'vi', + property: 'doMock', + message: + 'Use vi.mock() with vi.hoisted() instead of vi.doMock(). See docs/testing/vitest-patterns.md' + } + ] + } + }, { files: ['scripts/**/*.js'], languageOptions: { diff --git a/src/stores/firebaseAuthStore.test.ts b/src/stores/firebaseAuthStore.test.ts index bbad432640f..54beac934d9 100644 --- a/src/stores/firebaseAuthStore.test.ts +++ b/src/stores/firebaseAuthStore.test.ts @@ -82,6 +82,21 @@ vi.mock('@/stores/toastStore', () => ({ // Mock useDialogService vi.mock('@/services/dialogService') +const mockDistributionTypes = vi.hoisted(() => ({ + isCloud: false, + isDesktop: false +})) + +vi.mock('@/platform/distribution/types', () => mockDistributionTypes) + +const mockApiKeyStore = vi.hoisted(() => ({ + getAuthHeader: vi.fn().mockReturnValue(null) +})) + +vi.mock('@/stores/apiKeyAuthStore', () => ({ + useApiKeyAuthStore: () => mockApiKeyStore +})) + describe('useFirebaseAuthStore', () => { let store: ReturnType let authStateCallback: (user: any) => void @@ -147,12 +162,9 @@ describe('useFirebaseAuthStore', () => { }) describe('token refresh events', () => { - beforeEach(async () => { - vi.resetModules() - vi.doMock('@/platform/distribution/types', () => ({ - isCloud: true, - isDesktop: true - })) + beforeEach(() => { + mockDistributionTypes.isCloud = true + mockDistributionTypes.isDesktop = true vi.mocked(firebaseAuth.onIdTokenChanged).mockImplementation( (_auth, callback) => { @@ -164,8 +176,7 @@ describe('useFirebaseAuthStore', () => { vi.mocked(vuefire.useFirebaseAuth).mockReturnValue(mockAuth as any) setActivePinia(createPinia()) - const storeModule = await import('@/stores/firebaseAuthStore') - store = storeModule.useFirebaseAuthStore() + store = useFirebaseAuthStore() }) it("should not increment tokenRefreshTrigger on the user's first ID token event", () => { @@ -442,13 +453,8 @@ describe('useFirebaseAuthStore', () => { // This test reproduces the issue where getAuthHeader fails due to network errors // when Firebase Auth tries to refresh tokens offline - // Mock useApiKeyAuthStore to return null (no API key fallback) - const mockApiKeyStore = { - getAuthHeader: vi.fn().mockReturnValue(null) - } - vi.doMock('@/stores/apiKeyAuthStore', () => ({ - useApiKeyAuthStore: () => mockApiKeyStore - })) + // Configure mockApiKeyStore to return null (no API key fallback) + mockApiKeyStore.getAuthHeader.mockReturnValue(null) // Setup user with network error on token refresh mockUser.getIdToken.mockReset() diff --git a/src/workbench/extensions/manager/utils/versionUtil.test.ts b/src/workbench/extensions/manager/utils/versionUtil.test.ts index d1127368aa5..a9eacfc9d05 100644 --- a/src/workbench/extensions/manager/utils/versionUtil.test.ts +++ b/src/workbench/extensions/manager/utils/versionUtil.test.ts @@ -1,15 +1,16 @@ -import { describe, expect, it, vi } from 'vitest' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { checkVersionCompatibility, getFrontendVersion } from '@/workbench/extensions/manager/utils/versionUtil' -// Mock config module +const mockConfig = vi.hoisted((): { app_version: string | undefined } => ({ + app_version: '1.24.0-1' +})) + vi.mock('@/config', () => ({ - default: { - app_version: '1.24.0-1' - } + default: mockConfig })) describe('versionUtil', () => { @@ -266,79 +267,40 @@ describe('versionUtil', () => { }) describe('getFrontendVersion', () => { + let originalEnv: string | undefined + + beforeEach(() => { + originalEnv = import.meta.env.VITE_APP_VERSION + mockConfig.app_version = '1.24.0-1' + }) + + afterEach(() => { + if (originalEnv !== undefined) { + import.meta.env.VITE_APP_VERSION = originalEnv + } else { + delete import.meta.env.VITE_APP_VERSION + } + }) + it('should return app_version from config when available', () => { const version = getFrontendVersion() expect(version).toBe('1.24.0-1') }) - it('should fallback to VITE_APP_VERSION when app_version is not available', async () => { - // Save original environment - const originalEnv = import.meta.env.VITE_APP_VERSION - - // Mock config without app_version - vi.doMock('@/config', () => ({ - default: {} - })) - - // Set VITE_APP_VERSION + it('should fallback to VITE_APP_VERSION when app_version is not available', () => { + mockConfig.app_version = undefined import.meta.env.VITE_APP_VERSION = '2.0.0' - // Clear module cache to force re-import - vi.resetModules() - - // Import fresh module - const versionUtil = - await import('@/workbench/extensions/manager/utils/versionUtil') - - const version = versionUtil.getFrontendVersion() + const version = getFrontendVersion() expect(version).toBe('2.0.0') - - // Restore original env - import.meta.env.VITE_APP_VERSION = originalEnv - - // Reset mocks for next test - vi.resetModules() - vi.doMock('@/config', () => ({ - default: { - app_version: '1.24.0-1' - } - })) }) - it('should return undefined when no version is available', async () => { - // Save original environment - const originalEnv = import.meta.env.VITE_APP_VERSION - - // Mock config without app_version - vi.doMock('@/config', () => ({ - default: {} - })) - - // Clear VITE_APP_VERSION + it('should return undefined when no version is available', () => { + mockConfig.app_version = undefined delete import.meta.env.VITE_APP_VERSION - // Clear module cache to force re-import - vi.resetModules() - - // Import fresh module - const versionUtil = - await import('@/workbench/extensions/manager/utils/versionUtil') - - const version = versionUtil.getFrontendVersion() + const version = getFrontendVersion() expect(version).toBeUndefined() - - // Restore original env - if (originalEnv !== undefined) { - import.meta.env.VITE_APP_VERSION = originalEnv - } - - // Reset mocks for next test - vi.resetModules() - vi.doMock('@/config', () => ({ - default: { - app_version: '1.24.0-1' - } - })) }) }) })