refactor: extend vitest setup with full chrome/browser mocks and i18n utility mock
This commit is contained in:
+36
-13
@@ -1,18 +1,29 @@
|
|||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import { vi, beforeEach, afterEach } from 'vitest';
|
import { afterEach, beforeEach, vi } from 'vitest';
|
||||||
|
|
||||||
|
vi.mock('@/utils/useLazyTranslation', () => ({
|
||||||
|
useLazyTranslation: (ns?: string) => ({
|
||||||
|
// 自动承接命名空间前缀过滤,100% 模拟真实多语种直出
|
||||||
|
t: (key: string) => (ns ? `${ns}:${key}` : key),
|
||||||
|
i18n: {
|
||||||
|
changeLanguage: vi.fn().mockResolvedValue(undefined),
|
||||||
|
language: 'zh-CN',
|
||||||
|
},
|
||||||
|
isLoaded: true,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
// Mock react-i18next
|
|
||||||
vi.mock('react-i18next', () => ({
|
vi.mock('react-i18next', () => ({
|
||||||
useTranslation: () => ({
|
useTranslation: () => ({
|
||||||
t: (key: string) => key,
|
t: (key: string) => key,
|
||||||
i18n: {
|
i18n: {
|
||||||
changeLanguage: vi.fn(),
|
changeLanguage: vi.fn().mockResolvedValue(undefined),
|
||||||
language: 'zh-CN',
|
language: 'zh-CN',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
initReactI18next: {
|
initReactI18next: {
|
||||||
type: '3rdParty',
|
type: '3rdParty',
|
||||||
init: vi.fn(),
|
init: vi.fn().mockResolvedValue(undefined),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -36,14 +47,14 @@ const storageMock = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.defineProperty(global, 'chrome', {
|
const webExtensionMock = {
|
||||||
value: {
|
|
||||||
storage: storageMock,
|
storage: storageMock,
|
||||||
tabs: {
|
tabs: {
|
||||||
query: vi.fn().mockResolvedValue([]),
|
query: vi.fn().mockResolvedValue([]),
|
||||||
get: vi.fn(),
|
get: vi.fn().mockResolvedValue({}),
|
||||||
sendMessage: vi.fn().mockResolvedValue(undefined),
|
sendMessage: vi.fn().mockResolvedValue(undefined),
|
||||||
create: vi.fn().mockResolvedValue({}),
|
create: vi.fn().mockResolvedValue({}),
|
||||||
|
reload: vi.fn().mockResolvedValue(undefined), // ✅ 承接 MessageAction.RELOAD_TAB 刷新单元测试
|
||||||
},
|
},
|
||||||
runtime: {
|
runtime: {
|
||||||
id: 'test-extension-id',
|
id: 'test-extension-id',
|
||||||
@@ -59,6 +70,7 @@ Object.defineProperty(global, 'chrome', {
|
|||||||
addListener: vi.fn(),
|
addListener: vi.fn(),
|
||||||
removeListener: vi.fn(),
|
removeListener: vi.fn(),
|
||||||
},
|
},
|
||||||
|
openPopup: vi.fn().mockResolvedValue(undefined),
|
||||||
},
|
},
|
||||||
sidePanel: {
|
sidePanel: {
|
||||||
open: vi.fn().mockResolvedValue(undefined),
|
open: vi.fn().mockResolvedValue(undefined),
|
||||||
@@ -70,6 +82,13 @@ Object.defineProperty(global, 'chrome', {
|
|||||||
getAll: vi.fn().mockResolvedValue([]),
|
getAll: vi.fn().mockResolvedValue([]),
|
||||||
remove: vi.fn().mockResolvedValue(undefined),
|
remove: vi.fn().mockResolvedValue(undefined),
|
||||||
},
|
},
|
||||||
|
alarms: {
|
||||||
|
create: vi.fn().mockResolvedValue(undefined),
|
||||||
|
onAlarm: {
|
||||||
|
addListener: vi.fn(),
|
||||||
|
removeListener: vi.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
contextMenus: {
|
contextMenus: {
|
||||||
create: vi.fn(),
|
create: vi.fn(),
|
||||||
onClicked: {
|
onClicked: {
|
||||||
@@ -92,13 +111,18 @@ Object.defineProperty(global, 'chrome', {
|
|||||||
ACTION: 'action',
|
ACTION: 'action',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
writable: true,
|
|
||||||
});
|
Object.defineProperty(globalThis, 'chrome', { value: webExtensionMock, writable: true });
|
||||||
|
Object.defineProperty(globalThis, 'browser', { value: webExtensionMock, writable: true });
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
Object.defineProperty(window, 'chrome', { value: webExtensionMock, writable: true });
|
||||||
|
Object.defineProperty(window, 'browser', { value: webExtensionMock, writable: true });
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
// Ensure storage mocks return objects even after clearAllMocks
|
|
||||||
storageMock.local.get.mockResolvedValue({});
|
storageMock.local.get.mockResolvedValue({});
|
||||||
storageMock.session.get.mockResolvedValue({});
|
storageMock.session.get.mockResolvedValue({});
|
||||||
});
|
});
|
||||||
@@ -107,8 +131,7 @@ afterEach(() => {
|
|||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 全局 matchMedia mock(ThemeModeProvider 依赖)
|
// 全局 matchMedia 极客级环境模拟(ThemeModeProvider 依赖)
|
||||||
// 必须在 beforeEach 中设置,因为 afterEach 的 restoreAllMocks 会清除它
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
Object.defineProperty(window, 'matchMedia', {
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
writable: true,
|
writable: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user