Sumber yang diterbitkan
Unduh ZIP sumber
CH-J Server Manager
Jelajahi direktori dan file untuk rilis aplikasi tertentu.
CH-J / Server Manager
377 file
core-20261019T111616Z-160a00bfcddc
Ditambahkan: · Dibuat:
1
"use strict";2
// Run with Electron, not node. Uses the production renderer/preload/IPC and real local probes.3
const { app, clipboard, ipcMain, dialog } = require("electron");4
const assert = require("node:assert/strict");5
const fs = require("node:fs");6
const os = require("node:os");7
const path = require("node:path");8
const http = require("node:http");9
const zlib = require("node:zlib");10
const { once } = require("node:events");11
const { createMainWindow, hardenSession } = require("../src/main/bootstrap/createMainWindow");12
const { registerCoreIpc } = require("../src/main/ipc/registerCoreIpc");13
const { DiagnosticsService } = require("../src/main/diagnostics/diagnosticsService");14
const { ConfigStore } = require("../src/main/config/configStore");15
const root = fs.mkdtempSync(path.join(os.tmpdir(), "chj-diagnostics-ui-"));16
app.setPath("userData", root);17
let window, server, diagnostics;18
const errors = [];19
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));20
async function until(source, timeout = 15000) {21
const start = Date.now();22
while (Date.now() - start < timeout) { if (await window.webContents.executeJavaScript(source)) return; await wait(50); }23
throw new Error("UI condition timed out: " + source + " · " + await window.webContents.executeJavaScript(`JSON.stringify({ status: diagnosticsView.state.report?.status, error: diagnosticsView.state.report?.error, ping: diagnosticsView.state.report?.results.ping?.map((r) => [r.address, r.status, r.code, r.sent]), text: document.querySelector(".diag-status").textContent, visible: document.visibilityState })`) + " · errors " + JSON.stringify(errors));24
}25
async function run() {26
await app.whenReady();27
server = http.createServer((req, res) => {28
const body = Buffer.from("Local diagnostics UI smoke ".repeat(30));29
const encoder = { gzip: zlib.gzipSync, br: zlib.brotliCompressSync, deflate: zlib.deflateSync, zstd: zlib.zstdCompressSync }[req.headers["accept-encoding"]];30
res.setHeader("content-type", "text/plain");31
if (encoder) { res.setHeader("content-encoding", req.headers["accept-encoding"]); res.end(encoder(body)); } else res.end(body);32
});33
server.on("clientError", (_error, socket) => socket.destroy());34
server.listen(0, "127.0.0.1"); await once(server, "listening");35
diagnostics = new DiagnosticsService({ storageRoot: root });36
const configStore = new ConfigStore(root); configStore.load(); configStore.update({ updates: { autoCheck: false } });37
hardenSession(); window = createMainWindow();38
window.webContents.on("console-message", (event) => { if (event.level === "error") { errors.push(event.message); console.error(event.message); } });39
// Unrelated services stay offline in this test. All diagnostics use production implementations.40
registerCoreIpc({ ipcMain, app, clipboard, dialog, configStore, diagnosticsService: diagnostics,41
pluginService: { getState: () => ({ installed: [], catalog: [], windows: [] }) }, pluginRuntime: { notifyLanguageChanged() {} },42
vaultStore: { status: () => ({ unlocked: true }) }, profileService: { list: () => [] },43
updateService: { getState: () => ({ currentVersion: "0.0.1", status: "idle", releases: [] }) }, getMainWindow: () => window });44
diagnostics.on("progress", (value) => window.webContents.send("diagnostics:progress", value));45
await until('Boolean(document.querySelector(".diag-toolbar"))');46
assert.deepEqual(await window.webContents.executeJavaScript('Array.from(document.querySelectorAll(".sidebar [data-view], #hashToolButton")).map(n => n.dataset.view || "hash").filter(n => ["plugins","diagnostics","hash"].includes(n))'), ["plugins", "diagnostics", "hash"]);47
await window.webContents.executeJavaScript(`document.querySelector('[data-view="diagnostics"]').click(); document.querySelector('.diag-toolbar input').value = 'http://127.0.0.1:${server.address().port}/'; document.querySelector('#diag-panel-http .primary').click();`);48
await until('diagnosticsView.state.report?.status === "completed"');49
const result = await window.webContents.executeJavaScript('diagnosticsView.state.report');50
assert.equal(result.results.http[0].comparisons[0].samples[0].negotiated, "1.1");51
assert.equal(result.results.http[0].comparisons[0].samples[0].downloadedBytes, 810);52
assert.equal(result.results.http[0].comparisons[2].samples[0].status, "unavailable");53
assert.equal(await window.webContents.executeJavaScript('typeof window.require'), "undefined");54
for (const language of ["de", "en", "cs"]) await window.webContents.executeJavaScript(`applyLanguage('${language}'); document.querySelector('#diag-tab-http').click();`);55
await window.webContents.executeJavaScript('document.querySelector(".diag-controls select:last-of-type"); diagnosticsView.refreshLanguage();');56
// Narrow window, real compression and persistent history.57
// Diagnostics follows the dark application theme; it has no own theme selector.58
assert.equal(await window.webContents.executeJavaScript('document.querySelector("#diagnosticsView").dataset.theme'), "dark");59
assert.equal(await window.webContents.executeJavaScript('Array.from(document.querySelectorAll(".diag-controls select")).some((f) => f.querySelector("option[value=light]"))'), false);60
await window.webContents.executeJavaScript('Array.from(document.querySelectorAll("#diag-panel-http .primary"))[1].click()');61
await until('diagnosticsView.state.report?.results.compression && diagnosticsView.state.report.status === "completed"');62
assert.equal(await window.webContents.executeJavaScript('diagnosticsView.state.report.results.compression[0].results.find(r=>r.encoding==="br").status'), "success");63
assert.equal(await window.webContents.executeJavaScript('diagnosticsView.state.report.results.compression[0].decoder.runtime'), "bundled");64
await until('!document.querySelector("#diag-panel-ping .primary").disabled');65
// Intensive ICMP: 0.05 s interval, total count and advanced settings through the real OS ping (no root).66
await window.webContents.executeJavaScript(`document.querySelector('.diag-toolbar input').value = '127.0.0.1'; { const set = (name, value) => { const field = Array.from(document.querySelectorAll('.diag-ping-settings select, .diag-ping-settings input')).find((f) => f.closest('label')?.querySelector('[data-diag-text]')?.dataset.diagText === name); field.type === 'checkbox' ? field.checked = value : field.value = value; field.dispatchEvent(new Event(field.tagName === 'SELECT' || field.type === 'checkbox' ? 'change' : 'input')); }; set('Interval', '50'); set('Total packets', '40'); set('Ping timeout (ms)', '1000'); set('Payload size (bytes)', '100'); } document.querySelector('#diag-tab-ping').click(); document.querySelector('#diag-panel-ping .primary').click();`);67
await until('diagnosticsView.state.report?.results.ping && diagnosticsView.state.report.status === "completed"', 30000);68
const pinged = await window.webContents.executeJavaScript('diagnosticsView.state.report.results.ping[0]');69
assert.equal(pinged.status, "success"); assert.equal(pinged.sent, 40); assert.equal(pinged.timing.intervalMs, 50); assert.equal(pinged.timing.packetSize, 100);70
assert.ok(pinged.timing.effectiveIntervalMs < 80, "sub-second cadence: " + pinged.timing.effectiveIntervalMs);71
assert.match(await window.webContents.executeJavaScript('document.querySelector(".diag-ping-estimate").textContent'), /2 s/);72
// Manually entered IPv4 + IPv6 pair in one run, no DNS.73
await until('!document.querySelector("#diag-panel-ping .primary").disabled');74
await window.webContents.executeJavaScript(`{ const f = document.querySelector('.diag-toolbar input'); f.value = '127.0.0.1, ::1'; f.dispatchEvent(new Event('input')); const c = Array.from(document.querySelectorAll('.diag-ping-settings input')).find((x) => x.closest('label')?.querySelector('[data-diag-text]')?.dataset.diagText === 'Total packets'); c.value = '5'; c.dispatchEvent(new Event('input')); document.querySelector('#diag-panel-ping .primary').click(); }`);75
await until('diagnosticsView.state.report?.results.ping?.length === 2 && diagnosticsView.state.report.status === "completed"', 30000);76
assert.deepEqual(await window.webContents.executeJavaScript('diagnosticsView.state.report.results.ping.map((r) => [r.address, r.status, r.sent])'), [["127.0.0.1", "success", 5], ["::1", "success", 5]]);77
const history = diagnostics.history.list(); assert.equal(history.length, 4);78
assert.equal(new (require("../src/main/diagnostics/historyStore").DiagnosticsHistory)(root).list().length, 4);79
window.setSize(960, 720);80
await wait(100);81
assert.equal(await window.webContents.executeJavaScript("document.documentElement.scrollWidth <= window.innerWidth"), true);82
await window.webContents.executeJavaScript('document.querySelector("#diag-tab-history").click()'); await wait(100);83
assert.equal(await window.webContents.executeJavaScript('document.querySelectorAll("#diag-panel-history tbody tr").length'), 4);84
const preferences = window.webContents.getLastWebPreferences(); assert.equal(preferences.contextIsolation, true); assert.equal(preferences.sandbox, true); assert.equal(preferences.nodeIntegration, false);85
const artifacts = process.env.CHJ_DIAGNOSTICS_SMOKE_ARTIFACT_DIR;86
if (artifacts) { fs.mkdirSync(artifacts, { recursive: true }); await window.webContents.executeJavaScript('document.querySelector("#diag-tab-http").click()'); await wait(100); fs.writeFileSync(path.join(artifacts, "diagnostics-light.png"), (await Promise.race([window.webContents.capturePage(), wait(5000).then(() => { throw new Error("Screenshot capture timed out"); })])).toPNG()); }87
assert.deepEqual(errors, []);88
console.log("CHJ_DIAGNOSTICS_UI_OK: real HTTP/1.1, protocol failures, Brotli via bundled decoder, 0.05 s ping, history, CZ/DE/EN, app dark theme, manual IPv4+IPv6, sandbox");89
}90
run().then(() => finish(0), (error) => { console.error(error); finish(1); });91
let finishing = false;92
function finish(code) { if (finishing) return; finishing = true; diagnostics?.stopAll(); window?.destroy(); server?.close(); try { fs.rmSync(root, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 }); } catch (error) { console.error("Temporary Chromium cache cleanup:", error.code); } app.exit(code); }93
setTimeout(() => { console.error("Diagnostics UI smoke exceeded 90s"); finish(1); }, 90000).unref();SHA-256
51133842876984cc054f50e968c61d91aaf9526e54bf53f31d5888d66ccee26dCH-J Proprietary Software License 1.14 · Kode sumber disediakan berdasarkan CH-J Proprietary Software License 1.14. Ketersediaannya tidak mengubah ketentuan lisensi atau memberikan hak tambahan.
SHA-256 arsip
a9605c0870a223b6a8542bb0705edd51d8b04f3069582653417a8397fabcc09a