Skip to content

Commit

Permalink
refactor: improved typing, added more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thorsten committed Feb 8, 2025
1 parent 4a9828f commit 431ff5d
Show file tree
Hide file tree
Showing 13 changed files with 622 additions and 529 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
"vanilla-cookieconsent": "^3.1.0"
},
"devDependencies": {
"@babel/core": "^7.26.7",
"@babel/preset-env": "^7.26.7",
"@babel/core": "^7.26.8",
"@babel/preset-env": "^7.26.8",
"@commitlint/cli": "^19.7.1",
"@commitlint/config-conventional": "^19.7.1",
"@types/bootstrap": "^5.2.10",
Expand All @@ -64,10 +64,10 @@
"prettier": "^3.4.2",
"pretty-quick": "^4.0.0",
"rollup-plugin-sbom": "^1.1.1",
"sass": "^1.83.4",
"sass": "^1.84.0",
"sigmund": "^1.0.1",
"typescript": "^5.7.3",
"vite": "^6.0.11",
"vite": "^6.1.0",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.2",
"vite-plugin-minify": "^2.1.0",
Expand Down
13 changes: 0 additions & 13 deletions phpmyfaq/admin/assets/src/api/configuration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,17 +313,4 @@ describe('saveConfiguration', () => {
body: formData,
});
});

it('should throw an error if the network response is not ok', async () => {
global.fetch = vi.fn(() =>
Promise.resolve({
success: false,
} as unknown as Response)
);

const formData = new FormData();
formData.append('key', 'value');

await expect(saveConfiguration(formData)).rejects.toThrow('Network response was not ok.');
});
});
6 changes: 1 addition & 5 deletions phpmyfaq/admin/assets/src/api/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,7 @@ export const saveConfiguration = async (data: FormData): Promise<void> => {
body: data,
})) as unknown as Response;

if (response.success) {
return await response.json();
} else {
throw new Error('Network response was not ok.');
}
return await response.json();
} catch (error) {
throw error;
}
Expand Down
75 changes: 75 additions & 0 deletions phpmyfaq/admin/assets/src/api/stop-words.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { describe, it, expect, vi } from 'vitest';
import { fetchByLanguage, postStopWord, removeStopWord } from './stop-words';

global.fetch = vi.fn();

describe('Stop Words API', () => {
afterEach(() => {
vi.clearAllMocks();
});

it('fetchByLanguage should fetch stop words by language', async () => {
const mockResponse = [{ id: 1, lang: 'en', stopword: 'example' }];
(fetch as vi.Mock).mockResolvedValue({
ok: true,
json: async () => mockResponse,
});

const result = await fetchByLanguage('en');
expect(fetch).toHaveBeenCalledWith('./api/stopwords?language=en', {
method: 'GET',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
});
expect(result).toEqual(mockResponse);
});

it('postStopWord should post a new stop word', async () => {
const mockResponse = { success: true };
(fetch as vi.Mock).mockResolvedValue({
ok: true,
json: async () => mockResponse,
});

const result = await postStopWord('csrfToken', 'example', 1, 'en');
expect(fetch).toHaveBeenCalledWith('./api/stopword/save', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify({
csrf: 'csrfToken',
stopWord: 'example',
stopWordId: 1,
stopWordsLang: 'en',
}),
});
expect(result).toEqual(mockResponse);
});

it('removeStopWord should delete a stop word', async () => {
const mockResponse = { success: true };
(fetch as vi.Mock).mockResolvedValue({
ok: true,
json: async () => mockResponse,
});

const result = await removeStopWord('csrfToken', 1, 'en');
expect(fetch).toHaveBeenCalledWith('./api/stopword/delete', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify({
csrf: 'csrfToken',
stopWordId: 1,
stopWordsLang: 'en',
}),
});
expect(result).toEqual(mockResponse);
});
});
78 changes: 78 additions & 0 deletions phpmyfaq/admin/assets/src/api/stop-words.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* Fetch data for stop words
*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at https://mozilla.org/MPL/2.0/.
*
* @package phpMyFAQ
* @author Thorsten Rinne <[email protected]>
* @copyright 2025 phpMyFAQ Team
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
* @link https://www.phpmyfaq.de
* @since 2025-02-08
*/

export const fetchByLanguage = async (language: string): Promise<void> => {
try {
const response = await fetch(`./api/stopwords?language=${language}`, {
method: 'GET',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
});

return await response.json();
} catch (error) {
throw error;
}
};

export const postStopWord = async (
csrf: string,
stopWord: string,
stopWordId: number,
stopWordLanguage: string
): Promise<void> => {
try {
const response = await fetch('./api/stopword/save', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify({
csrf: csrf,
stopWord: stopWord,
stopWordId: stopWordId,
stopWordsLang: stopWordLanguage,
}),
});

return await response.json();
} catch (error) {
throw error;
}
};

export const removeStopWord = async (csrf: string, stopWordId: number, stopWordLanguage: string): Promise<void> => {
try {
const response = await fetch('./api/stopword/delete', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify({
csrf: csrf,
stopWordId: stopWordId,
stopWordsLang: stopWordLanguage,
}),
});

return await response.json();
} catch (error) {
throw error;
}
};
2 changes: 1 addition & 1 deletion phpmyfaq/admin/assets/src/api/upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface ResponseData {
message?: string;
}

export const fetchHealthCheck = async (): Promise<ResponseData | undefined> => {
export const fetchHealthCheck = async (): Promise<ResponseData> => {
try {
const response = await fetch(`./api/health-check`, {
method: 'GET',
Expand Down
8 changes: 4 additions & 4 deletions phpmyfaq/admin/assets/src/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ export const handleConfiguration = async (): Promise<void> => {
const configTabList: HTMLElement[] = [].slice.call(document.querySelectorAll('#configuration-list a'));
const result = document.getElementById('pmf-configuration-result') as HTMLElement;
if (configTabList.length) {
let tabLoaded = false;
let tabLoaded: boolean = false;
configTabList.forEach((element: HTMLElement): void => {
const configTabTrigger = new Tab(element);
element.addEventListener('shown.bs.tab', async (event) => {
element.addEventListener('shown.bs.tab', async (event: Event): Promise<void> => {
event.preventDefault();
const target = (event.target as HTMLAnchorElement).getAttribute('href') as string;
await handleConfigurationTab(target);
Expand Down Expand Up @@ -85,10 +85,10 @@ export const handleConfiguration = async (): Promise<void> => {
};

export const handleSaveConfiguration = async (): Promise<void> => {
const saveConfigurationButton = document.getElementById('save-configuration');
const saveConfigurationButton = document.getElementById('save-configuration') as HTMLButtonElement;

if (saveConfigurationButton) {
saveConfigurationButton.addEventListener('click', async (event) => {
saveConfigurationButton.addEventListener('click', async (event: Event): Promise<void> => {
event.preventDefault();
const form = document.getElementById('configuration-list') as HTMLFormElement;
const formData = new FormData(form);
Expand Down
10 changes: 5 additions & 5 deletions phpmyfaq/admin/assets/src/configuration/elasticsearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const handleElasticsearch = async (): Promise<void> => {
const buttons: NodeListOf<HTMLButtonElement> = document.querySelectorAll('button.pmf-elasticsearch');

if (buttons) {
buttons.forEach((element: HTMLButtonElement) => {
buttons.forEach((element: HTMLButtonElement): void => {
element.addEventListener('click', async (event: Event): Promise<void> => {
event.preventDefault();

Expand Down Expand Up @@ -51,11 +51,11 @@ export const handleElasticsearch = async (): Promise<void> => {
const response = (await fetchElasticsearchStatistics()) as unknown as ElasticsearchResponse;

if (response.index) {
const indexName = response.index;
const indexName = response.index as string;
const stats = response.stats;
const count = stats.indices[indexName].total.docs.count;
const sizeInBytes = stats.indices[indexName].total.store.size_in_bytes;
let html = '<dl class="row">';
const count: number = stats.indices[indexName].total.docs.count ?? 0;
const sizeInBytes: number = stats.indices[indexName].total.store.size_in_bytes ?? 0;
let html: string = '<dl class="row">';
html += `<dt class="col-sm-3">Documents</dt><dd class="col-sm-9">${count ?? 0}</dd>`;
html += `<dt class="col-sm-3">Storage size</dt><dd class="col-sm-9">${formatBytes(sizeInBytes ?? 0)}</dd>`;
html += '</dl>';
Expand Down
Loading

0 comments on commit 431ff5d

Please sign in to comment.