060-webapps-core.js 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. WebApp wave 1: core daily-driver apps.
  3. Smoke coverage for the highest-importance WebApps - the default
  4. openers for everyday file types - served by the real ArozOS server
  5. with a real authenticated session:
  6. NotepadA, Text, Photo, Music, Video, PDF Viewer, Zip File Manager
  7. Each app must load its entry page and render its key UI element.
  8. NotepadA additionally opens a real file through the same
  9. hash-parameter convention the desktop uses (ao_module_loadInputFiles).
  10. */
  11. "use strict";
  12. const h = require("../lib/system-harness");
  13. // App entry pages and the element that proves the app booted.
  14. const APPS = [
  15. { name: "NotepadA", path: "/NotepadA/index.html", selector: "#codeArea" },
  16. { name: "Text", path: "/Text/index.html", selector: "#toolbar" },
  17. { name: "Photo", path: "/Photo/index.html", selector: "#content-area" },
  18. { name: "Music", path: "/Music/index.html", selector: "#mainMenu" },
  19. { name: "Video", path: "/Video/index.html", selector: "#playList" },
  20. { name: "PDF Viewer", path: "/PDF%20Viewer/viewer.html", selector: "#outerContainer" },
  21. { name: "Zip File Manager", path: "/Zip%20File%20Manager/index.html", selector: "#listContainer" }
  22. ];
  23. h.run("WEBAPPS-CORE", async function (env) {
  24. const base = env.baseURL;
  25. const page = await h.newPage(env.browser);
  26. await h.loginViaAPI(page, base, env.admin.username, env.admin.password);
  27. // ── 1. Every core app boots and renders its main UI ──
  28. for (const app of APPS) {
  29. await page.goto(base + app.path, { waitUntil: "domcontentloaded" });
  30. try {
  31. await page.waitForSelector(app.selector, { state: "attached", timeout: 20000 });
  32. } catch (e) {
  33. h.fail(app.name + " did not render " + app.selector + " at " + app.path);
  34. }
  35. h.ok(app.name + " boots and renders its main UI");
  36. }
  37. // ── 2. NotepadA opens a real file through the desktop convention ──
  38. const csrft = await h.csrfToken(page, base);
  39. const resp = await h.postForm(page, base + "/system/file_system/newItem", {
  40. type: "file", src: "user:/", filename: "e2e-open.txt", csrft: csrft
  41. });
  42. if (resp.toLowerCase().indexOf("ok") === -1) h.fail("could not create test file: " + resp);
  43. const fileRef = encodeURIComponent(JSON.stringify([
  44. { filename: "e2e-open.txt", filepath: "user:/e2e-open.txt" }
  45. ]));
  46. await page.goto(base + "/NotepadA/index.html#" + fileRef, { waitUntil: "domcontentloaded" });
  47. await page.waitForSelector("#codeArea", { state: "attached", timeout: 20000 });
  48. try {
  49. // Each opened file becomes a .fileTab carrying its filepath in the
  50. // "filename" attribute (the visible label loads asynchronously).
  51. await page.waitForFunction(function () {
  52. var tabs = document.querySelectorAll(".fileTab");
  53. for (var i = 0; i < tabs.length; i++) {
  54. var fn = tabs[i].getAttribute("filename") || "";
  55. if (fn.indexOf("e2e-open.txt") !== -1) { return true; }
  56. }
  57. return false;
  58. }, { timeout: 20000 });
  59. } catch (e) {
  60. h.fail("NotepadA did not open e2e-open.txt in a tab");
  61. }
  62. h.ok("NotepadA opens a file passed via the desktop hash convention");
  63. // ── 3. Music app can see the user's storage roots ──
  64. // (Music builds its library from the same listRoots/listDir APIs; a
  65. // quick API probe under this session guards the data path the app uses.)
  66. const roots = await h.getJSON(page, base + "/system/file_system/listRoots");
  67. if (JSON.stringify(roots).indexOf("user") === -1) {
  68. h.fail("media apps have no user root to browse");
  69. }
  70. h.ok("media apps have the user storage root available");
  71. // Cleanup
  72. const csrft2 = await h.csrfToken(page, base);
  73. await h.postForm(page, base + "/system/file_system/fileOpr", {
  74. opr: "delete", src: JSON.stringify(["user:/e2e-open.txt"]), csrft: csrft2
  75. });
  76. await page.close();
  77. });