090-webapps-utilities.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. WebApp wave 4: utilities / developer / network apps.
  3. Smoke coverage for the remaining WebApps served by the real ArozOS
  4. server with an authenticated session:
  5. Calculator, Clock, Browser, Speedtest, Web Downloader,
  6. Web Builder, SQLite Admin, Terminal, AGIForge, AIChat, OTPAuth,
  7. Productivity, OnScreenKeyboard, Arozcast, Management Gateway,
  8. UnitTest, CronDemo, Serverless
  9. Each app must load its entry page and render its key UI element.
  10. Calculator additionally does a real end-to-end calculation through
  11. its own UI to prove interactivity, not just rendering.
  12. */
  13. "use strict";
  14. const h = require("../lib/system-harness");
  15. const APPS = [
  16. { name: "Calculator", path: "/Calculator/index.html", selector: "#expression" },
  17. { name: "Clock", path: "/Clock/index.html", selector: "#panel-clock" },
  18. { name: "Browser", path: "/Browser/index.html", selector: "#urlbar" },
  19. { name: "Speedtest", path: "/Speedtest/index.html", selector: "#progressTrack" },
  20. { name: "Web Downloader", path: "/Web%20Downloader/index.html", selector: "#downloadbtn" },
  21. { name: "Web Builder", path: "/Web%20Builder/index.html", selector: "#editorFrame" },
  22. { name: "SQLite Admin", path: "/SQLite%20Admin/index.html", selector: "#btn-open-db" },
  23. { name: "Terminal", path: "/Terminal/index.html", selector: "#termOutput" },
  24. { name: "AGIForge", path: "/AGIForge/index.html", selector: "#convo" },
  25. { name: "AIChat", path: "/AIChat/index.html", selector: ".composer" },
  26. { name: "OTPAuth", path: "/OTPAuth/index.html", selector: "#sidebar" },
  27. { name: "Productivity", path: "/Productivity/index.html", selector: "#toolGrid" },
  28. { name: "OnScreenKeyboard", path: "/OnScreenKeyboard/index.html", selector: ".keyboard" },
  29. { name: "Arozcast", path: "/Arozcast/index.html", selector: "#app" },
  30. { name: "Management Gateway", path: "/Management%20Gateway/index.html", selector: "#mainframe" },
  31. { name: "UnitTest", path: "/UnitTest/index.html", selector: "#btnRunAll" },
  32. { name: "CronDemo", path: "/CronDemo/index.html", selector: "#status-card" },
  33. { name: "Serverless", path: "/Serverless/index.html", selector: "#global-stats" }
  34. ];
  35. h.run("WEBAPPS-UTILITIES", async function (env) {
  36. const base = env.baseURL;
  37. const page = await h.newPage(env.browser);
  38. await h.loginViaAPI(page, base, env.admin.username, env.admin.password);
  39. page.on("dialog", function (d) { d.dismiss().catch(function () {}); });
  40. // ── 1. Every utility app boots and renders its main UI ──
  41. for (const app of APPS) {
  42. await page.goto(base + app.path, { waitUntil: "domcontentloaded" });
  43. try {
  44. await page.waitForSelector(app.selector, { state: "attached", timeout: 20000 });
  45. } catch (e) {
  46. h.fail(app.name + " did not render " + app.selector + " at " + app.path);
  47. }
  48. h.ok(app.name + " boots and renders its main UI");
  49. }
  50. // ── 2. Calculator performs a real calculation through its UI ──
  51. await page.goto(base + "/Calculator/index.html", { waitUntil: "domcontentloaded" });
  52. await page.waitForSelector("#result", { state: "attached", timeout: 20000 });
  53. // Buttons carry their glyph as text; click 7 + 8 = and read the result.
  54. async function clickKey(label) {
  55. await page.click("xpath=(//button[normalize-space(.)='" + label + "'])[1]");
  56. }
  57. await clickKey("7");
  58. await clickKey("+");
  59. await clickKey("8");
  60. await clickKey("=");
  61. await page.waitForFunction(function () {
  62. var r = document.getElementById("result");
  63. return r && r.textContent.replace(/[^0-9]/g, "").indexOf("15") !== -1;
  64. }, { timeout: 10000 }).catch(function () {
  65. h.fail("Calculator did not compute 7 + 8 = 15");
  66. });
  67. h.ok("Calculator computes 7 + 8 = 15 through its UI");
  68. await page.close();
  69. });