LCOV - code coverage report
Current view: top level - pkg/playground - test.js Coverage Total Hit
Test: cockpit Lines: 81.6 % 152 124
Test Date: 2026-07-13 10:00:01

            Line data    Source code
       1              : // SPDX-License-Identifier: LGPL-2.1-or-later
       2           11 : import cockpit from "cockpit";
       3              : 
       4              : import { Channel } from '../lib/cockpit/channel';
       5              : 
       6              : import '../lib/patternfly/patternfly-6-cockpit.scss';
       7              : import "../../node_modules/@patternfly/patternfly/components/Button/button.css";
       8              : import "../../node_modules/@patternfly/patternfly/components/Page/page.css";
       9              : 
      10           11 : document.addEventListener("DOMContentLoaded", () => {
      11            0 :     document.getElementById("hammer").addEventListener("click", e => e.target.setAttribute("hidden", "hidden"));
      12              : 
      13            1 :     document.querySelector(".cockpit-internal-reauthorize .pf-v6-c-button").addEventListener("click", () => {
      14            1 :         document.querySelector(".cockpit-internal-reauthorize span").textContent = "checking...";
      15            1 :         cockpit.script("pkcheck --action-id org.freedesktop.policykit.exec --process $$ -u 2>&1", { superuser: "try" })
      16            1 :                 .stream(data => console.debug(data))
      17            1 :                 .then(() => {
      18            1 :                     document.querySelector(".cockpit-internal-reauthorize span").textContent = "result: authorized";
      19            1 :                 })
      20            1 :                 .catch(() => {
      21            1 :                     document.querySelector(".cockpit-internal-reauthorize span").textContent = "result: access-denied";
      22            1 :                 });
      23            1 :     });
      24              : 
      25            3 :     document.querySelector(".super-channel .pf-v6-c-button").addEventListener("click", () => {
      26            3 :         document.querySelector(".super-channel span").textContent = "checking...";
      27            3 :         cockpit.spawn(["id"], { superuser: "require" })
      28            2 :                 .then(data => {
      29            2 :                     console.log("done");
      30            2 :                     document.querySelector(".super-channel span").textContent = "result: " + data;
      31            2 :                 })
      32            1 :                 .catch(ex => {
      33            1 :                     console.log("fail");
      34            1 :                     document.querySelector(".super-channel span").textContent = "result: " + ex.problem;
      35            1 :                 });
      36            3 :     });
      37              : 
      38            3 :     document.querySelector(".lock-channel .pf-v6-c-button").addEventListener("click", () => {
      39            3 :         document.querySelector(".lock-channel span").textContent = "locking...";
      40            3 :         cockpit.spawn(["flock", "-o", "/tmp/playground-test-lock", "-c", "echo locked; sleep infinity"],
      41            3 :                       { superuser: "try", err: "message" })
      42            3 :                 .stream(data => {
      43            3 :                     document.querySelector(".lock-channel span").textContent = data;
      44            3 :                 })
      45            1 :                 .catch(ex => {
      46            1 :                     document.querySelector(".lock-channel span").textContent = "failed: " + ex.toString();
      47            1 :                 });
      48            3 :     });
      49              : 
      50           11 :     function update_nav() {
      51           11 :         document.getElementById("nav").textContent = '';
      52           11 :         const path = ["top"].concat(cockpit.location.path);
      53           11 :         const e_nav = document.getElementById("nav");
      54           11 :         path.forEach((p, i) => {
      55            2 :             if (i < path.length - 1) {
      56            2 :                 const e_link = document.createElement("a");
      57            2 :                 e_link.setAttribute("tabindex", "0");
      58            2 :                 e_link.textContent = p;
      59            0 :                 e_link.addEventListener("click", () => cockpit.location.go(path.slice(1, i + 1)));
      60            2 :                 e_nav.append(e_link, " >> ");
      61            2 :             } else {
      62           11 :                 const e_span = document.createElement("span");
      63           11 :                 e_span.textContent = p;
      64           11 :                 e_nav.appendChild(e_span);
      65           11 :             }
      66           11 :         });
      67           11 :     }
      68              : 
      69           11 :     cockpit.addEventListener('locationchanged', update_nav);
      70           11 :     update_nav();
      71              : 
      72            0 :     document.getElementById('go-down').addEventListener("click", () => {
      73            0 :         const len = cockpit.location.path.length;
      74            0 :         cockpit.location.go(cockpit.location.path.concat(len.toString()), { length: len.toString() });
      75            0 :     });
      76              : 
      77           11 :     const counter = cockpit.file("/tmp/counter", { syntax: JSON });
      78              : 
      79           11 :     function normalize_counter(obj) {
      80           11 :         obj = obj || { };
      81           11 :         obj.counter = obj.counter || 0;
      82           11 :         return obj;
      83           11 :     }
      84              : 
      85            0 :     function complain(error) {
      86            0 :         document.getElementById('file-error').textContent = error.toString();
      87            0 :     }
      88              : 
      89           11 :     function changed(content, tag, error) {
      90           11 :         if (error)
      91            2 :             return complain(error);
      92           11 :         document.getElementById('file-content').textContent = normalize_counter(content).counter;
      93           11 :         document.getElementById('file-error').textContent = "";
      94           11 :     }
      95              : 
      96           11 :     counter.watch(changed);
      97              : 
      98            0 :     document.getElementById('modify-file').addEventListener("click", () => {
      99            0 :         counter
     100            0 :                 .modify(obj => {
     101            0 :                     obj = normalize_counter(obj);
     102            0 :                     obj.counter += 1;
     103            0 :                     return obj;
     104            0 :                 })
     105            0 :                 .catch(complain);
     106            0 :     });
     107              : 
     108           11 :     function load_file() {
     109           11 :         cockpit.file("/tmp/counter").read()
     110           11 :                 .then(content => {
     111           11 :                     document.getElementById('edit-file').value = content;
     112           11 :                 });
     113           11 :     }
     114              : 
     115            0 :     function save_file() {
     116            0 :         cockpit.file("/tmp/counter").replace(document.getElementById('edit-file').value);
     117            0 :     }
     118              : 
     119           11 :     document.getElementById('load-file').addEventListener("click", load_file);
     120           11 :     document.getElementById('save-file').addEventListener("click", save_file);
     121           11 :     load_file();
     122              : 
     123            0 :     document.getElementById('delete-file').addEventListener("click", () => cockpit.spawn(["rm", "-f", "/tmp/counter"]));
     124              : 
     125           11 :     document.body.removeAttribute("hidden");
     126              : 
     127           12 :     function show_hidden() {
     128            6 :         document.getElementById("hidden").textContent = cockpit.hidden ? "hidden" : "visible";
     129           12 :     }
     130              : 
     131           11 :     cockpit.user().then(info => {
     132           11 :         console.log(info);
     133           11 :         document.getElementById("user-info").textContent = JSON.stringify(info);
     134           11 :     });
     135              : 
     136           11 :     cockpit.addEventListener("visibilitychange", show_hidden);
     137           11 :     show_hidden();
     138              : 
     139              :     // HACK: The user/group/mode options are not part yet of the Cockpit File API so
     140              :     // we resort to creating our own channel here. We can't use the new `Channel`
     141              :     // API as importing it with cockpit leads to the wrong cockpit.Channel being
     142              :     // used instead of the new class.
     143            2 :     const replace = (filename, content, tag, attrs) => {
     144            2 :         const channel = new Channel({ payload: "fsreplace1", superuser: 'try', path: filename, tag, attrs });
     145            2 :         channel.wait();
     146              : 
     147            2 :         return new Promise((resolve, reject) => {
     148            2 :             channel.on('close', message => {
     149            0 :                 if (message.problem) {
     150            0 :                     reject(message);
     151            0 :                 } else {
     152            2 :                     resolve();
     153            2 :                 }
     154            2 :             });
     155              : 
     156            2 :             channel.send_data(content);
     157            2 :             channel.send_control({ command: 'done' });
     158            2 :         });
     159            2 :     };
     160              : 
     161           11 :     const fsreplace_btn = document.getElementById("fsreplace1-create");
     162           11 :     const fsreplace_error = document.getElementById("fsreplace1-error");
     163            2 :     fsreplace_btn.addEventListener("click", e => {
     164            2 :         fsreplace_btn.disabled = true;
     165            2 :         fsreplace_error.textContent = '';
     166            2 :         const filename = document.getElementById("fsreplace1-filename").value;
     167            2 :         const content = document.getElementById("fsreplace1-content").value;
     168            2 :         const use_tag = document.getElementById("fsreplace1-use-tag").checked;
     169            2 :         const file = cockpit.file(filename, { superuser: "try" });
     170            2 :         const attrs = { };
     171            2 :         for (const field of ["user", "group", "mode"]) {
     172            2 :             const val = document.getElementById(`fsreplace1-${field}`).value;
     173            2 :             if (!val)
     174            2 :                 continue;
     175              : 
     176            1 :             attrs[field] = val;
     177            1 :         }
     178              : 
     179            2 :         if ('mode' in attrs)
     180            1 :             attrs.mode = Number.parseInt(attrs.mode);
     181              : 
     182            2 :         file.read().then((_content, tag) => {
     183            0 :             replace(filename, content, use_tag ? tag : undefined, attrs).catch(exc => {
     184            0 :                 fsreplace_error.textContent = cockpit.message(exc);
     185            0 :             })
     186            2 :                     .finally(() => {
     187            2 :                         fsreplace_btn.disabled = false;
     188            2 :                     });
     189            2 :         });
     190            2 :     });
     191           11 : });
        

Generated by: LCOV version 2.0-1