mirror of
https://github.com/Corfirean/coa-server-manager.git
synced 2026-11-11 03:51:01 +00:00
70 lines
4.6 KiB
JavaScript
70 lines
4.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { createRequire } from "node:module";
|
|
import { fileURLToPath } from "node:url";
|
|
import { rolldown } from "rolldown";
|
|
import { createElement } from "react";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
|
|
const stubs = {
|
|
react: `export const useEffect=()=>{}; export const useCallback=f=>f; export const useRef=v=>({current:v}); export const useState=v=>[globalThis.__overviewStateCalls++===0?globalThis.__overviewStatus:v,()=>{}];`,
|
|
"@/lib/api": `export const api={}; export const asUiError=e=>e;`,
|
|
"@/lib/utils": `export const cn=(...s)=>s.filter(Boolean).join(' '); export const formatBytes=String; export const formatUptime=String;`,
|
|
"@/i18n": `export const useT=()=>k=>k; export const useHuman=()=>h=>h;`,
|
|
"@/lib/serverUpdate": `export const serverUpdateBlocksRestart=()=>false; export const applyServerUpdate=async()=>false; export const useServerUpdate=()=>globalThis.__overviewUpdate;`,
|
|
"@/lib/clientJob": `export const dismissClientJob=()=>{}; export const startClientUpdate=()=>{}; export const stopClientJob=()=>{}; export const syncClient=()=>{}; export const useClientJob=()=>({phase:'idle'});`,
|
|
"@/lib/clientUpdate": `export const checkClient=()=>{}; export const useClientStatus=()=>({status:null});`,
|
|
"@/lib/autoRestartPrefs": `export const useAutoRestart=()=>[false,()=>{}];`,
|
|
"./ForceStopDialog": `export const ForceStopDialog=()=>null;`,
|
|
"@/screens/PublishCard": `export const ListingChip=()=>null;`,
|
|
"@/screens/PublishDialog": `export const PublishRealmDialog=()=>null;`,
|
|
"@/lib/registry": `export const useRegistryStatus=()=>({status:null});`,
|
|
"@/lib/publishRealms": `export const usePublishRealms=()=>[];`,
|
|
"@/components/ui/button": `import {createElement} from 'react'; export const Button=({children,disabled,onClick,className})=>createElement('button',{disabled,onClick,className},children);`,
|
|
"@/components/ui/card": `import {createElement} from 'react'; export const Card=({children,...props})=>createElement('div',props,children);`,
|
|
};
|
|
const bundle = await rolldown({
|
|
input: fileURLToPath(new URL("../src/screens/Overview.tsx", import.meta.url)),
|
|
transform: { jsx: "react-jsx" },
|
|
external: (id, importer) => id === "react/jsx-runtime" || id === "lucide-react" || (id === "react" && !importer?.endsWith("Overview.tsx")),
|
|
plugins: [{ name: "overview-test",
|
|
resolveId(id, importer) {
|
|
if (id === "./ForceStopDialog") return "\0" + id;
|
|
if (id === "@/lib/serverLifecycle") return fileURLToPath(new URL("../src/lib/serverLifecycle.ts", import.meta.url));
|
|
if (id === "@/components/ui/split-button") return fileURLToPath(new URL("../src/components/ui/split-button.tsx", import.meta.url));
|
|
if (id.startsWith("@/") || (id === "react" && importer?.endsWith("Overview.tsx"))) return "\0" + id;
|
|
},
|
|
load(id) {
|
|
if (!id.startsWith("\0")) return;
|
|
const name = id.slice(1);
|
|
return stubs[name] ?? `export const ${name.split('/').at(-1)}=()=>null;`;
|
|
},
|
|
}],
|
|
});
|
|
const result = await bundle.generate({ format: "cjs" });
|
|
await bundle.close();
|
|
const module = { exports: {} };
|
|
new Function("require", "module", "exports", result.output[0].code)(createRequire(import.meta.url), module, module.exports);
|
|
|
|
function overview(update) {
|
|
globalThis.__overviewStateCalls = 0;
|
|
globalThis.__overviewStatus = { path_exists: true, busy: false, observed: Object.fromEntries(["mysql", "auth", "world"].map(k => [k, { state: "stopped" }])) };
|
|
globalThis.__overviewUpdate = { available: false, applying: false, preview: null, uiError: null, stateError: null, ...update };
|
|
return renderToStaticMarkup(createElement(module.exports.Overview, { server: { id: "fixture", path: "C:/CoA_Server" }, onForget() {}, onOpenUpdates() {}, onRealmChanged() {}, onReport() {} }));
|
|
}
|
|
const failure = { human: { code: "unknown", title: "Server update failed", message: "See the technical details." }, technical: "Stop this repack before moving its folder or changing its ports." };
|
|
|
|
test("Overview displays failed updates after the progress and cached offer disappear", () => {
|
|
const html = overview({ uiError: failure });
|
|
assert.match(html, /role="alert"/);
|
|
assert.match(html, /Server update failed/);
|
|
assert.match(html, /common.viewDetails/);
|
|
assert.match(html, /common.copyError/);
|
|
});
|
|
test("Overview displays update-state failures even without an update offer", () => {
|
|
assert.match(overview({ stateError: failure }), /Server update failed/);
|
|
});
|
|
test("Overview does not display an update failure when there is none", () => {
|
|
assert.doesNotMatch(overview({}), /Server update failed/);
|
|
});
|