mirror of
https://github.com/Quad4-Software/MeshChatX.git
synced 2026-08-18 09:49:09 -04:00
131 lines
5.3 KiB
JavaScript
131 lines
5.3 KiB
JavaScript
const { test, expect } = require("@playwright/test");
|
|
|
|
const E2E_BACKEND_PORT = process.env.E2E_BACKEND_PORT || "18079";
|
|
const E2E_BACKEND_ORIGIN = `http://127.0.0.1:${E2E_BACKEND_PORT}`;
|
|
|
|
test.describe("MeshChatX E2E (Vite + Python backend)", () => {
|
|
test("backend /api/v1/status is OK (via Vite proxy)", async ({ request }) => {
|
|
const res = await request.get("/api/v1/status");
|
|
expect(res.ok()).toBeTruthy();
|
|
const body = await res.json();
|
|
expect(body.status).toBe("ok");
|
|
});
|
|
|
|
test("backend /api/v1/self-test returns success for all checks", async ({ request }) => {
|
|
const res = await request.get("/api/v1/self-test");
|
|
expect(res.ok()).toBeTruthy();
|
|
const body = await res.json();
|
|
const keys = [
|
|
"stack_up",
|
|
"config_good",
|
|
"db_good",
|
|
"read_write_good",
|
|
"identity_good",
|
|
"imports_good",
|
|
"storage_lock_good",
|
|
"temp_fs_good",
|
|
"public_assets_good",
|
|
"lxmf_router_good",
|
|
"subprocess_good",
|
|
"run_module_good",
|
|
"sqlite_roundtrip",
|
|
"identity_roundtrip",
|
|
"loopback_tcp",
|
|
"unicode_path_good",
|
|
"rnode_support_good",
|
|
"bot_launcher_good",
|
|
"http_status_good",
|
|
"http_app_info_good",
|
|
"http_config_good",
|
|
"http_db_health_good",
|
|
"http_auth_csrf_good",
|
|
"http_bots_status_good",
|
|
"http_security_good",
|
|
"http_interfaces_good",
|
|
"http_reticulum_instance_good",
|
|
"http_identities_good",
|
|
"http_favourites_good",
|
|
"http_telephone_good",
|
|
"http_plugins_good",
|
|
"http_plugins_trust_good",
|
|
"http_sideband_plugins_good",
|
|
"http_sideband_config_good",
|
|
"http_rrc_hubs_good",
|
|
"http_rrc_servers_good",
|
|
"plugins_runtime_good",
|
|
"websocket_good",
|
|
"websocket_rns_link_good",
|
|
"bots_lifecycle",
|
|
];
|
|
for (const key of keys) {
|
|
expect(body[key], key).toBeDefined();
|
|
expect(body[key].status, `${key}: ${body[key].reason || "(no reason)"}`).toBe("ok");
|
|
}
|
|
});
|
|
|
|
test("backend /api/v1/app/info returns version JSON (direct backend)", async ({ request }) => {
|
|
const res = await request.get(`${E2E_BACKEND_ORIGIN}/api/v1/app/info`);
|
|
expect(res.ok()).toBeTruthy();
|
|
const body = await res.json();
|
|
expect(body.app_info).toBeDefined();
|
|
expect(String(body.app_info.version).length).toBeGreaterThan(0);
|
|
});
|
|
|
|
test("backend /api/v1/app/sessions returns active session list", async ({ request }) => {
|
|
const res = await request.get(`${E2E_BACKEND_ORIGIN}/api/v1/app/sessions`);
|
|
expect(res.ok()).toBeTruthy();
|
|
const body = await res.json();
|
|
expect(typeof body.count).toBe("number");
|
|
expect(Array.isArray(body.sessions)).toBeTruthy();
|
|
expect(typeof body.warning).toBe("boolean");
|
|
expect(typeof body.warning_enabled).toBe("boolean");
|
|
for (const session of body.sessions) {
|
|
expect(session).toHaveProperty("id");
|
|
expect(session).toHaveProperty("ip");
|
|
expect(session).toHaveProperty("user_agent");
|
|
expect(session).toHaveProperty("connected_at");
|
|
}
|
|
});
|
|
|
|
test("document title, shell, and app name in header", async ({ page }) => {
|
|
await page.goto("/");
|
|
await expect(page).toHaveTitle(/Reticulum MeshChatX/);
|
|
await expect(page.getByText("Reticulum MeshChatX", { exact: true }).first()).toBeVisible({
|
|
timeout: 30000,
|
|
});
|
|
const root = page.locator("#app");
|
|
await expect(root).toBeVisible();
|
|
await expect(root.locator("div").first()).toBeVisible({ timeout: 30000 });
|
|
});
|
|
|
|
test("about page shows MeshChatX and version", async ({ page }) => {
|
|
await page.goto("/#/about");
|
|
await expect(page).toHaveURL(/#\/about/);
|
|
await expect(page.getByText("MeshChatX", { exact: true }).first()).toBeVisible({ timeout: 30000 });
|
|
await expect(page.locator("#app")).toBeVisible();
|
|
await expect(page.getByText("Active sessions", { exact: true }).first()).toBeVisible({
|
|
timeout: 30000,
|
|
});
|
|
});
|
|
|
|
test("settings route loads profile section", async ({ page }) => {
|
|
await page.goto("/#/settings");
|
|
await expect(page).toHaveURL(/#\/settings/);
|
|
await expect(page.getByText("Profile", { exact: true }).first()).toBeVisible({ timeout: 30000 });
|
|
});
|
|
|
|
test("messages route is reachable", async ({ page }) => {
|
|
await page.goto("/#/messages");
|
|
await expect(page).toHaveURL(/#\/messages/);
|
|
await expect(page.locator("#app")).toBeVisible();
|
|
});
|
|
|
|
test("debug logs route shows Logs and Access attempts tabs", async ({ page }) => {
|
|
await page.goto("/#/debug/logs");
|
|
await expect(page).toHaveURL(/#\/debug\/logs/);
|
|
await expect(page.getByRole("button", { name: "Logs", exact: true })).toBeVisible({ timeout: 30000 });
|
|
await expect(page.getByRole("button", { name: "Access attempts", exact: true })).toBeVisible({
|
|
timeout: 30000,
|
|
});
|
|
});
|
|
});
|