Skip to content

Commit 5a7c2eb

Browse files
committed
feat: Improve error handling in services and update related tests for consistency
1 parent b60748a commit 5a7c2eb

10 files changed

+78
-49
lines changed

packages/database/src/mix-database-data-rest-portal-service.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,15 @@ export class MixDatabaseDataRestPortalService {
6868
return { isSucceed: false, errors: ['Missing file'] };
6969
}
7070
const endpoint = `${this.prefixUrl}/import-data/${mixDatabaseName}`;
71+
if (!mixDatabaseName) {
72+
return { isSucceed: false, errors: ['Missing mixDatabaseName'] };
73+
}
74+
if (!file) {
75+
return { isSucceed: false, errors: ['Missing file'] };
76+
}
7177
const formData = new FormData();
7278
formData.append('file', file);
73-
const url = new URL(endpoint, this.api['config'].apiBaseUrl).toString();
74-
try {
75-
const res = await fetch(url, {
76-
method: 'POST',
77-
body: formData,
78-
headers: this.api['config'].apiKey ? { 'Authorization': `Bearer ${this.api['config'].apiKey}` } : undefined,
79-
});
80-
const data = await res.json().catch(() => undefined);
81-
if (!res.ok) {
82-
return { isSucceed: false, data, errors: [res.statusText], status: res.status };
83-
}
84-
return { isSucceed: true, data, status: res.status };
85-
} catch (err) {
86-
return { isSucceed: false, errors: [(err as Error).message] };
87-
}
79+
return this.api.post(endpoint, formData, { isFormData: true });
8880
}
8981

9082
/**

packages/database/src/module-data-rest-mvc-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class ModuleDataRestMvcService {
2424
*/
2525
async initForm(moduleId: string): Promise<ApiResult> {
2626
if (!moduleId) {
27-
return { isSucceed: false, errors: ['Missing moduleId'] };
27+
throw new Error('Missing moduleId');
2828
}
2929
const endpoint = `${this.prefixUrl}/init-form/${moduleId}`;
3030
return this.api.get(endpoint);

packages/database/tests/mix-database-column-rest-service.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ApiService } from './api-services';
2-
import { MixDatabaseColumnRestService } from './mix-database-column-rest-service';
1+
import { ApiService } from '@mixcore/api';
2+
import { MixDatabaseColumnRestService } from '../src/mix-database-column-rest-service';
33

44
describe('MixDatabaseColumnRestService', () => {
55
let api: ApiService;
@@ -14,8 +14,10 @@ describe('MixDatabaseColumnRestService', () => {
1414
expect(columnService).toBeInstanceOf(MixDatabaseColumnRestService);
1515
});
1616

17-
it('should throw if no mixDatabaseName provided', async () => {
18-
await expect(columnService.initData('')).rejects.toThrow('Missing mixDatabaseName');
17+
it('should return error if no mixDatabaseName provided', async () => {
18+
const result = await columnService.initData('');
19+
expect(result.isSucceed).toBe(false);
20+
expect(result.errors).toContain('Missing mixDatabaseName');
1921
});
2022

2123
it('should call initData', async () => {

packages/database/tests/mix-database-data-rest-client-service.test.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ApiService } from './api-services';
2-
import { MixDatabaseDataRestClientService } from './mix-database-data-rest-client-service';
1+
import { ApiService } from '@mixcore/api';
2+
import { MixDatabaseDataRestClientService } from '../src/mix-database-data-rest-client-service';
33

44
describe('MixDatabaseDataRestClientService', () => {
55
let api: ApiService;
@@ -14,8 +14,10 @@ describe('MixDatabaseDataRestClientService', () => {
1414
expect(clientService).toBeInstanceOf(MixDatabaseDataRestClientService);
1515
});
1616

17-
it('should throw if no mixDatabaseName for initData', async () => {
18-
await expect(clientService.initData('')).rejects.toThrow('Missing mixDatabaseName');
17+
it('should return error if no mixDatabaseName for initData', async () => {
18+
const result = await clientService.initData('');
19+
expect(result.isSucceed).toBe(false);
20+
expect(result.errors).toContain('Missing mixDatabaseName');
1921
});
2022

2123
it('should call initData', async () => {
@@ -25,8 +27,10 @@ describe('MixDatabaseDataRestClientService', () => {
2527
expect(api.get).toHaveBeenCalledWith('/mix-database-data/form/init/testdb');
2628
});
2729

28-
it('should throw if no mixDatabaseName for saveData', async () => {
29-
await expect(clientService.saveData('', {})).rejects.toThrow('Missing mixDatabaseName');
30+
it('should return error if no mixDatabaseName for saveData', async () => {
31+
const result = await clientService.saveData('', {});
32+
expect(result.isSucceed).toBe(false);
33+
expect(result.errors).toContain('Missing mixDatabaseName');
3034
});
3135

3236
it('should call saveData', async () => {
@@ -36,8 +40,10 @@ describe('MixDatabaseDataRestClientService', () => {
3640
expect(api.post).toHaveBeenCalledWith('/mix-database-data/form/save-data/testdb/true', { foo: 'bar' });
3741
});
3842

39-
it('should throw if no dataId for saveValues', async () => {
40-
await expect(clientService.saveValues('', {})).rejects.toThrow('Missing dataId');
43+
it('should return error if no dataId for saveValues', async () => {
44+
const result = await clientService.saveValues('', {});
45+
expect(result.isSucceed).toBe(false);
46+
expect(result.errors).toContain('Missing dataId');
4147
});
4248

4349
it('should call saveValues', async () => {

packages/database/tests/mix-database-data-rest-portal-service.test.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ApiService } from './api-services';
2-
import { MixDatabaseDataRestPortalService } from './mix-database-data-rest-portal-service';
1+
import { ApiService } from '@mixcore/api';
2+
import { MixDatabaseDataRestPortalService } from '../src/mix-database-data-rest-portal-service';
33

44
describe('MixDatabaseDataRestPortalService', () => {
55
let api: ApiService;
@@ -35,8 +35,10 @@ describe('MixDatabaseDataRestPortalService', () => {
3535
expect(api.get).toHaveBeenCalledWith('/mix-database-data/portal/additional-data');
3636
});
3737

38-
it('should throw if no mixDatabaseName for initData', async () => {
39-
await expect(portalService.initData('')).rejects.toThrow('Missing mixDatabaseName');
38+
it('should return error if no mixDatabaseName for initData', async () => {
39+
const result = await portalService.initData('');
40+
expect(result.isSucceed).toBe(false);
41+
expect(result.errors).toContain('Missing mixDatabaseName');
4042
});
4143

4244
it('should call initData', async () => {
@@ -60,24 +62,31 @@ describe('MixDatabaseDataRestPortalService', () => {
6062
expect(api.get).toHaveBeenCalledWith('/mix-database-data/portal/export');
6163
});
6264

63-
it('should throw if no mixDatabaseName for import', async () => {
64-
await expect(portalService.import('', new File([''], 'test.txt'))).rejects.toThrow('Missing mixDatabaseName');
65+
it('should return error if no mixDatabaseName for import', async () => {
66+
const result = await portalService.import('', new File([''], 'test.txt'));
67+
expect(result.isSucceed).toBe(false);
68+
expect(result.errors).toContain('Missing mixDatabaseName');
6569
});
6670

67-
it('should throw if no file for import', async () => {
68-
await expect(portalService.import('testdb', null as any)).rejects.toThrow('Missing file');
71+
it('should return error if no file for import', async () => {
72+
const result = await portalService.import('testdb', null as any);
73+
expect(result.isSucceed).toBe(false);
74+
expect(result.errors).toContain('Missing file');
6975
});
7076

7177
it('should call import', async () => {
7278
const fakeFile = new File(['test'], 'test.txt', { type: 'text/plain' });
7379
globalThis.fetch = jest.fn().mockResolvedValue({ ok: true, json: async () => ({ imported: true }) });
7480
const result = await portalService.import('testdb', fakeFile);
75-
expect(result).toEqual({ imported: true });
81+
expect(result.data).toEqual({ imported: true });
82+
expect(result.isSucceed).toBe(true);
7683
expect(globalThis.fetch).toHaveBeenCalled();
7784
});
7885

79-
it('should throw if no mixDatabaseId for migrate', async () => {
80-
await expect(portalService.migrate('')).rejects.toThrow('Missing mixDatabaseId');
86+
it('should return error if no mixDatabaseId for migrate', async () => {
87+
const result = await portalService.migrate('');
88+
expect(result.isSucceed).toBe(false);
89+
expect(result.errors).toContain('Missing mixDatabaseId');
8190
});
8291

8392
it('should call migrate', async () => {

packages/database/tests/mix-database-data-value-rest-service.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ApiService } from './api-services';
2-
import { MixDatabaseDataValueRestService } from './mix-database-data-value-rest-service';
1+
import { ApiService } from '@mixcore/api';
2+
import { MixDatabaseDataValueRestService } from '../src/mix-database-data-value-rest-service';
33

44
describe('MixDatabaseDataValueRestService', () => {
55
let api: ApiService;

packages/database/tests/module-data-rest-mvc-service.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ApiService } from './api-services';
2-
import { ModuleDataRestMvcService } from './module-data-rest-mvc-service';
1+
import { ApiService } from '@mixcore/api';
2+
import { ModuleDataRestMvcService } from '../src/module-data-rest-mvc-service';
33

44
describe('ModuleDataRestMvcService', () => {
55
let api: ApiService;

packages/database/tests/module-data-services.test.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
1-
import { ModuleDataService } from './module-data-services';
1+
import { ModuleDataService } from '../src/module-data-services';
2+
import { ApiService } from '@mixcore/api';
23

4+
const api = new ApiService({ apiBaseUrl: 'https://mixcore.net' });
35
const config = {
46
apiBaseUrl: 'https://mixcore.net',
7+
api,
58
apiKey: process.env.MIXCORE_API_KEY || '',
69
};
710

811
describe('ModuleDataService', () => {
912
const service = new ModuleDataService(config);
1013

14+
beforeEach(() => {
15+
// Mock API response to match ApiResult format expected by service
16+
globalThis.fetch = jest.fn().mockResolvedValue({
17+
ok: true,
18+
json: async () => ({
19+
items: []
20+
})
21+
});
22+
});
23+
1124
it('fetchDataItems should return an array', async () => {
12-
const items = await service.fetchDataItems('1');
13-
expect(Array.isArray(items)).toBe(true);
25+
const result = await service.fetchDataItems('1');
26+
console.log('Test result:', result);
27+
expect(result).toBeDefined();
28+
expect(result.data).toBeDefined();
29+
expect(result.data.items).toBeDefined();
30+
expect(Array.isArray(result.data.items)).toBe(true);
1431
});
1532

1633
// Note: createDataItem and deleteDataItem require valid credentials and real data

packages/database/tests/related-attribute-data-rest-form-service.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { RelatedAttributeDataRestFormService } from './related-attribute-data-rest-form-service';
1+
import { RelatedAttributeDataRestFormService } from '../src/related-attribute-data-rest-form-service';
2+
import { ApiService } from '@mixcore/api';
23

34
describe('RelatedAttributeDataRestFormService', () => {
45
it('should instantiate with correct endpoint', () => {
5-
const service = new RelatedAttributeDataRestFormService();
6+
const api = new ApiService({ apiBaseUrl: 'http://localhost/api/' });
7+
const service = new RelatedAttributeDataRestFormService(api);
68
// @ts-expect-error endpoint is protected/private in base, this is a placeholder for real test
79
expect(service.endpoint).toBe('mix-database-data-association/form');
810
});

packages/database/tests/related-attribute-data-rest-portal-service.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { ApiService } from '@mixcore/api';
33

44
describe('RelatedAttributeDataRestPortalService', () => {
55
it('should instantiate with correct endpoint', () => {
6-
const service = new RelatedAttributeDataRestPortalService();
6+
const api = new ApiService({ apiBaseUrl: 'http://localhost/api/' });
7+
const service = new RelatedAttributeDataRestPortalService(api);
78
// @ts-expect-error endpoint is protected/private in base, this is a placeholder for real test
89
expect(service.endpoint).toBe('mix-database-data-association/portal');
910
});

0 commit comments

Comments
 (0)