import type child_process from "child_process"; import { describe, beforeAll, afterAll } from "vitest"; let etapiAuthToken: string | undefined; const getEtapiAuthorizationHeader = (): string => "Basic " + Buffer.from(`etapi:${etapiAuthToken}`).toString("base64"); const PORT: string = "9999"; const HOST: string = "http://localhost:" + PORT; type SpecDefinitionsFunc = () => void; function describeEtapi(description: string, specDefinitions: SpecDefinitionsFunc): void { describe(description, () => { let appProcess: ReturnType; beforeAll(async () => {}); afterAll(() => {}); specDefinitions(); }); } async function getEtapiResponse(url: string): Promise { return await fetch(`${HOST}/etapi/${url}`, { method: "GET", headers: { Authorization: getEtapiAuthorizationHeader() } }); } async function getEtapi(url: string): Promise { const response = await getEtapiResponse(url); return await processEtapiResponse(response); } async function getEtapiContent(url: string): Promise { const response = await fetch(`${HOST}/etapi/${url}`, { method: "GET", headers: { Authorization: getEtapiAuthorizationHeader() } }); checkStatus(response); return response; } async function postEtapi(url: string, data: Record = {}): Promise { const response = await fetch(`${HOST}/etapi/${url}`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: getEtapiAuthorizationHeader() }, body: JSON.stringify(data) }); return await processEtapiResponse(response); } async function postEtapiContent(url: string, data: BodyInit): Promise { const response = await fetch(`${HOST}/etapi/${url}`, { method: "POST", headers: { "Content-Type": "application/octet-stream", Authorization: getEtapiAuthorizationHeader() }, body: data }); checkStatus(response); return response; } async function putEtapi(url: string, data: Record = {}): Promise { const response = await fetch(`${HOST}/etapi/${url}`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: getEtapiAuthorizationHeader() }, body: JSON.stringify(data) }); return await processEtapiResponse(response); } async function putEtapiContent(url: string, data?: BodyInit): Promise { const response = await fetch(`${HOST}/etapi/${url}`, { method: "PUT", headers: { "Content-Type": "application/octet-stream", Authorization: getEtapiAuthorizationHeader() }, body: data }); checkStatus(response); return response; } async function patchEtapi(url: string, data: Record = {}): Promise { const response = await fetch(`${HOST}/etapi/${url}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: getEtapiAuthorizationHeader() }, body: JSON.stringify(data) }); return await processEtapiResponse(response); } async function deleteEtapi(url: string): Promise { const response = await fetch(`${HOST}/etapi/${url}`, { method: "DELETE", headers: { Authorization: getEtapiAuthorizationHeader() } }); return await processEtapiResponse(response); } async function processEtapiResponse(response: Response): Promise { const text = await response.text(); if (response.status < 200 || response.status >= 300) { throw new Error(`ETAPI error ${response.status}: ${text}`); } return text?.trim() ? JSON.parse(text) : null; } function checkStatus(response: Response): void { if (response.status < 200 || response.status >= 300) { throw new Error(`ETAPI error ${response.status}`); } } export default { describeEtapi, getEtapi, getEtapiResponse, getEtapiContent, postEtapi, postEtapiContent, putEtapi, putEtapiContent, patchEtapi, deleteEtapi };