Skip to content

Commit 47a1a23

Browse files
committed
refactor: moved API methods into own files
1 parent b3b9545 commit 47a1a23

File tree

13 files changed

+389
-98
lines changed

13 files changed

+389
-98
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { describe, it, expect, vi, afterEach } from 'vitest';
2+
import { fetchElasticsearchAction, fetchElasticsearchStatistics } from './elasticsearch';
3+
4+
describe('Elasticsearch API', () => {
5+
afterEach(() => {
6+
vi.restoreAllMocks();
7+
});
8+
9+
describe('fetchElasticsearchAction', () => {
10+
it('should fetch Elasticsearch action and return JSON response if successful', async () => {
11+
const mockResponse = { success: true, message: 'Action executed' };
12+
global.fetch = vi.fn(() =>
13+
Promise.resolve({
14+
ok: true,
15+
json: () => Promise.resolve(mockResponse),
16+
} as Response)
17+
);
18+
19+
const action = 'some-action';
20+
const result = await fetchElasticsearchAction(action);
21+
22+
expect(result).toEqual(mockResponse);
23+
expect(global.fetch).toHaveBeenCalledWith('./api/elasticsearch/some-action', {
24+
method: 'GET',
25+
cache: 'no-cache',
26+
headers: {
27+
'Content-Type': 'application/json',
28+
},
29+
redirect: 'follow',
30+
referrerPolicy: 'no-referrer',
31+
});
32+
});
33+
34+
it('should throw an error if fetch fails', async () => {
35+
const mockError = new Error('Fetch failed');
36+
global.fetch = vi.fn(() => Promise.reject(mockError));
37+
38+
const action = 'some-action';
39+
40+
await expect(fetchElasticsearchAction(action)).rejects.toThrow(mockError);
41+
});
42+
});
43+
44+
describe('fetchElasticsearchStatistics', () => {
45+
it('should fetch Elasticsearch statistics and return JSON response if successful', async () => {
46+
const mockResponse = {
47+
index: 'index-name',
48+
stats: {
49+
indices: {
50+
'index-name': {
51+
total: {
52+
docs: {
53+
count: 100,
54+
},
55+
store: {
56+
size_in_bytes: 1024,
57+
},
58+
},
59+
},
60+
},
61+
},
62+
};
63+
global.fetch = vi.fn(() =>
64+
Promise.resolve({
65+
ok: true,
66+
json: () => Promise.resolve(mockResponse),
67+
} as Response)
68+
);
69+
70+
const result = await fetchElasticsearchStatistics();
71+
72+
expect(result).toEqual(mockResponse);
73+
expect(global.fetch).toHaveBeenCalledWith('./api/elasticsearch/statistics', {
74+
method: 'GET',
75+
cache: 'no-cache',
76+
headers: {
77+
'Content-Type': 'application/json',
78+
},
79+
redirect: 'follow',
80+
referrerPolicy: 'no-referrer',
81+
});
82+
});
83+
84+
it('should throw an error if fetch fails', async () => {
85+
const mockError = new Error('Fetch failed');
86+
global.fetch = vi.fn(() => Promise.reject(mockError));
87+
88+
await expect(fetchElasticsearchStatistics()).rejects.toThrow(mockError);
89+
});
90+
});
91+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Fetch data for Elasticsearch configuration
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public License,
5+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
6+
* obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* @package phpMyFAQ
9+
* @author Thorsten Rinne <[email protected]>
10+
* @copyright 2025 phpMyFAQ Team
11+
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
12+
* @link https://www.phpmyfaq.de
13+
* @since 2025-01-26
14+
*/
15+
16+
import { ElasticsearchResponse, Response } from '../interfaces';
17+
18+
export const fetchElasticsearchAction = async (action: string): Promise<Response> => {
19+
try {
20+
const response = await fetch(`./api/elasticsearch/${action}`, {
21+
method: 'GET',
22+
cache: 'no-cache',
23+
headers: {
24+
'Content-Type': 'application/json',
25+
},
26+
redirect: 'follow',
27+
referrerPolicy: 'no-referrer',
28+
});
29+
30+
return await response.json();
31+
} catch (error) {
32+
throw error;
33+
}
34+
};
35+
36+
export const fetchElasticsearchStatistics = async (): Promise<ElasticsearchResponse> => {
37+
try {
38+
const response = await fetch('./api/elasticsearch/statistics', {
39+
method: 'GET',
40+
cache: 'no-cache',
41+
headers: {
42+
'Content-Type': 'application/json',
43+
},
44+
redirect: 'follow',
45+
referrerPolicy: 'no-referrer',
46+
});
47+
48+
return await response.json();
49+
} catch (error) {
50+
throw error;
51+
}
52+
};

phpmyfaq/admin/assets/src/api/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export * from './faqs';
55
export * from './forms';
66
export * from './glossary';
77
export * from './group';
8+
export * from './instance';
89
export * from './news';
910
export * from './question';
1011
export * from './statistics';
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { describe, it, expect, vi, afterEach } from 'vitest';
2+
import { addInstance, deleteInstance } from './instance';
3+
4+
describe('Instance API', () => {
5+
afterEach(() => {
6+
vi.restoreAllMocks();
7+
});
8+
9+
describe('addInstance', () => {
10+
it('should add instance and return JSON response if successful', async () => {
11+
const mockResponse = { added: '123', url: 'http://example.com', deleted: '' };
12+
global.fetch = vi.fn(() =>
13+
Promise.resolve({
14+
ok: true,
15+
json: () => Promise.resolve(mockResponse),
16+
} as Response)
17+
);
18+
19+
const csrf = 'csrfToken';
20+
const url = 'http://example.com';
21+
const instance = 'instanceName';
22+
const comment = 'comment';
23+
const email = '[email protected]';
24+
const admin = 'admin';
25+
const password = 'password';
26+
const result = await addInstance(csrf, url, instance, comment, email, admin, password);
27+
28+
expect(result).toEqual(mockResponse);
29+
expect(global.fetch).toHaveBeenCalledWith('./api/faq/search', {
30+
method: 'POST',
31+
headers: {
32+
Accept: 'application/json, text/plain, */*',
33+
'Content-Type': 'application/json',
34+
},
35+
body: JSON.stringify({
36+
csrf: csrf,
37+
url: url,
38+
instance: instance,
39+
comment: comment,
40+
email: email,
41+
admin: admin,
42+
password: password,
43+
}),
44+
});
45+
});
46+
47+
it('should throw an error if fetch fails', async () => {
48+
const mockError = new Error('Fetch failed');
49+
global.fetch = vi.fn(() => Promise.reject(mockError));
50+
51+
const csrf = 'csrfToken';
52+
const url = 'http://example.com';
53+
const instance = 'instanceName';
54+
const comment = 'comment';
55+
const email = '[email protected]';
56+
const admin = 'admin';
57+
const password = 'password';
58+
59+
await expect(addInstance(csrf, url, instance, comment, email, admin, password)).rejects.toThrow(mockError);
60+
});
61+
});
62+
63+
describe('deleteInstance', () => {
64+
it('should delete instance and return JSON response if successful', async () => {
65+
const mockResponse = { added: '', url: '', deleted: '123' };
66+
global.fetch = vi.fn(() =>
67+
Promise.resolve({
68+
ok: true,
69+
json: () => Promise.resolve(mockResponse),
70+
} as Response)
71+
);
72+
73+
const csrf = 'csrfToken';
74+
const instanceId = '123';
75+
const result = await deleteInstance(csrf, instanceId);
76+
77+
expect(result).toEqual(mockResponse);
78+
expect(global.fetch).toHaveBeenCalledWith('./api/instance/delete', {
79+
method: 'DELETE',
80+
headers: {
81+
Accept: 'application/json, text/plain, */*',
82+
'Content-Type': 'application/json',
83+
},
84+
body: JSON.stringify({
85+
csrf: csrf,
86+
instanceId: instanceId,
87+
}),
88+
});
89+
});
90+
91+
it('should throw an error if fetch fails', async () => {
92+
const mockError = new Error('Fetch failed');
93+
global.fetch = vi.fn(() => Promise.reject(mockError));
94+
95+
const csrf = 'csrfToken';
96+
const instanceId = '123';
97+
98+
await expect(deleteInstance(csrf, instanceId)).rejects.toThrow(mockError);
99+
});
100+
});
101+
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Fetch data for instance configuration
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public License,
5+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
6+
* obtain one at https://mozilla.org/MPL/2.0/.
7+
*
8+
* @package phpMyFAQ
9+
* @author Thorsten Rinne <[email protected]>
10+
* @copyright 2025 phpMyFAQ Team
11+
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
12+
* @link https://www.phpmyfaq.de
13+
* @since 2025-01-26
14+
*/
15+
16+
import { InstanceResponse } from '../interfaces';
17+
18+
export const addInstance = async (
19+
csrf: string,
20+
url: string,
21+
instance: string,
22+
comment: string,
23+
email: string,
24+
admin: string,
25+
password: string
26+
): Promise<InstanceResponse> => {
27+
try {
28+
const response = await fetch(`./api/faq/search`, {
29+
method: 'POST',
30+
headers: {
31+
Accept: 'application/json, text/plain, */*',
32+
'Content-Type': 'application/json',
33+
},
34+
body: JSON.stringify({
35+
csrf: csrf,
36+
url: url,
37+
instance: instance,
38+
comment: comment,
39+
email: email,
40+
admin: admin,
41+
password: password,
42+
}),
43+
});
44+
45+
return await response.json();
46+
} catch (error) {
47+
throw error;
48+
}
49+
};
50+
51+
export const deleteInstance = async (csrf: string, instanceId: string): Promise<InstanceResponse> => {
52+
try {
53+
const response = await fetch('./api/instance/delete', {
54+
method: 'DELETE',
55+
headers: {
56+
Accept: 'application/json, text/plain, */*',
57+
'Content-Type': 'application/json',
58+
},
59+
body: JSON.stringify({
60+
csrf: csrf,
61+
instanceId: instanceId,
62+
}),
63+
});
64+
65+
return await response.json();
66+
} catch (error) {
67+
throw error;
68+
}
69+
};

0 commit comments

Comments
 (0)