|
@@ -0,0 +1,128 @@
|
|
|
+import { fetchI18nMessages } from './i18nActions';
|
|
|
+
|
|
|
+// 模拟 axios 实例
|
|
|
+jest.mock('../interceptor', () => ({
|
|
|
+ get: jest.fn(),
|
|
|
+}));
|
|
|
+
|
|
|
+import axiosInstance from '../interceptor';
|
|
|
+
|
|
|
+describe('i18nActions', () => {
|
|
|
+ const mockAxiosGet = axiosInstance.get as jest.MockedFunction<
|
|
|
+ typeof axiosInstance.get
|
|
|
+ >;
|
|
|
+
|
|
|
+ beforeEach(() => {
|
|
|
+ jest.clearAllMocks();
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('fetchI18nMessages', () => {
|
|
|
+ it('should parse object data correctly', async () => {
|
|
|
+ const mockData = {
|
|
|
+ greeting: 'Hello, world!',
|
|
|
+ name: 'John Doe',
|
|
|
+ patient: 'Patient Management',
|
|
|
+ register: 'Register',
|
|
|
+ tasklist: 'Task List',
|
|
|
+ historylist: 'History List',
|
|
|
+ archivelist: 'Archive List',
|
|
|
+ bin: 'Recycle Bin',
|
|
|
+ outputlist: 'Transfer List',
|
|
|
+ exam: 'Examination',
|
|
|
+ examlist: 'Examination List',
|
|
|
+ process: 'Process',
|
|
|
+ print: 'Print',
|
|
|
+ printlist: 'Print List',
|
|
|
+ worklist: 'Task List',
|
|
|
+ 'worklist.operationPanel': 'Operation Panel',
|
|
|
+ 'register.basicInfoPanel': 'Basic Information Form Area',
|
|
|
+ 'register.protocolListPanel': 'Protocol Selection List Area',
|
|
|
+ };
|
|
|
+
|
|
|
+ mockAxiosGet.mockResolvedValue({ data: mockData });
|
|
|
+
|
|
|
+ const result = await fetchI18nMessages('en');
|
|
|
+
|
|
|
+ expect(result).toEqual(mockData);
|
|
|
+ expect(mockAxiosGet).toHaveBeenCalledWith('/pub/trans/en/en.js');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should parse JSON string data correctly', async () => {
|
|
|
+ const mockData = {
|
|
|
+ greeting: 'Hello, world!',
|
|
|
+ name: 'John Doe',
|
|
|
+ patient: 'Patient Management',
|
|
|
+ };
|
|
|
+ const mockJsonString = JSON.stringify(mockData);
|
|
|
+
|
|
|
+ mockAxiosGet.mockResolvedValue({ data: mockJsonString });
|
|
|
+
|
|
|
+ const result = await fetchI18nMessages('en');
|
|
|
+
|
|
|
+ expect(result).toEqual(mockData);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should handle non-string values by converting them', async () => {
|
|
|
+ const mockData = {
|
|
|
+ greeting: 'Hello, world!',
|
|
|
+ count: 123,
|
|
|
+ isActive: true,
|
|
|
+ nullValue: null,
|
|
|
+ undefinedValue: undefined,
|
|
|
+ };
|
|
|
+
|
|
|
+ mockAxiosGet.mockResolvedValue({ data: mockData });
|
|
|
+
|
|
|
+ const result = await fetchI18nMessages('en');
|
|
|
+
|
|
|
+ expect(result).toEqual({
|
|
|
+ greeting: 'Hello, world!',
|
|
|
+ count: '123',
|
|
|
+ isActive: 'true',
|
|
|
+ // null 和 undefined 值应该被跳过
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should throw error for invalid JSON string', async () => {
|
|
|
+ const invalidJsonString = '{ invalid json }';
|
|
|
+
|
|
|
+ mockAxiosGet.mockResolvedValue({ data: invalidJsonString });
|
|
|
+
|
|
|
+ await expect(fetchI18nMessages('en')).rejects.toThrow(
|
|
|
+ 'Invalid i18n data: failed to parse JSON string'
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should throw error for non-object data', async () => {
|
|
|
+ mockAxiosGet.mockResolvedValue({ data: 'not an object' });
|
|
|
+
|
|
|
+ await expect(fetchI18nMessages('en')).rejects.toThrow(
|
|
|
+ 'Invalid i18n data: failed to parse JSON string'
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should handle API errors', async () => {
|
|
|
+ mockAxiosGet.mockRejectedValue(new Error('Network error'));
|
|
|
+
|
|
|
+ await expect(fetchI18nMessages('en')).rejects.toThrow(
|
|
|
+ 'Failed to load i18n messages for locale: en'
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ it('should skip invalid keys', async () => {
|
|
|
+ const mockData = {
|
|
|
+ validKey: 'Valid Value',
|
|
|
+ '': 'Empty key should be skipped',
|
|
|
+ ' ': 'Whitespace key should be skipped',
|
|
|
+ };
|
|
|
+
|
|
|
+ mockAxiosGet.mockResolvedValue({ data: mockData });
|
|
|
+
|
|
|
+ const result = await fetchI18nMessages('en');
|
|
|
+
|
|
|
+ expect(result).toEqual({
|
|
|
+ validKey: 'Valid Value',
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+});
|