// Copyright (C) 2026 Danilo M. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Run: node desktop/modules/qtmaildir/test_ini.js // Ini.js is a QML library, so its .pragma line is stripped before node // evaluates it. const fs = require("fs"); const assert = require("assert"); const src = fs.readFileSync(__dirname + "/Ini.js", "utf8") .replace(/^\.pragma library$/m, ""); const I = new Function(src + "\nreturn { sections, entries, get, set, remove, addSection, removeSection };")(); const file = [ "[general]", "; startup_query = Unread", "toolbar_icon_size = 32", "date_format = dd/MM/yyyy hh:mm", "", "[account.gmail]", "maildir = gmail ; relative to notmuch's mail root", "drafts = [Gmail]/Bozze", 'send_command = "/usr/bin/msmtp -a x ; y"', "label = GM", "", "[tagcolors]", "shopping/amazon = #ff9900", "", ].join("\n"); // A value holding brackets is not a section header (AGENTS.md: three of // five accounts once lost their label to exactly that). assert.deepStrictEqual(I.sections(file), ["general", "account.gmail", "tagcolors"]); assert.strictEqual(I.get(file, "account.gmail", "drafts"), "[Gmail]/Bozze"); assert.strictEqual(I.get(file, "account.gmail", "label"), "GM"); // An inline comment is not part of the value; a quoted ; is. assert.strictEqual(I.get(file, "account.gmail", "maildir"), "gmail"); assert.strictEqual(I.get(file, "account.gmail", "send_command"), "/usr/bin/msmtp -a x ; y"); // A commented key is unset. assert.strictEqual(I.get(file, "general", "startup_query"), undefined); assert.deepStrictEqual(I.entries(file, "tagcolors"), [{ key: "shopping/amazon", value: "#ff9900" }]); // Replacing keeps the inline comment and every other line. let t = I.set(file, "account.gmail", "maildir", "gm2"); assert.strictEqual(t.split("\n")[6], "maildir = gm2 ; relative to notmuch's mail root"); assert.strictEqual(t.split("\n").length, file.split("\n").length); // Setting a commented key activates its line. t = I.set(file, "general", "startup_query", "Inbox"); assert.strictEqual(t.split("\n")[1], "startup_query = Inbox"); // Unsetting comments a key out in place. t = I.set(file, "general", "toolbar_icon_size", null); assert.strictEqual(t.split("\n")[2], "; toolbar_icon_size = 32"); assert.strictEqual(I.get(t, "general", "toolbar_icon_size"), undefined); // A new key lands at the end of its section, before the blank line. t = I.set(file, "general", "language", "it"); assert.strictEqual(t.split("\n")[4], "language = it"); assert.strictEqual(t.split("\n")[5], ""); assert.strictEqual(I.get(t, "general", "language"), "it"); // A value with a ; or a quote is quoted, and reads back the same. t = I.set(file, "account.gmail", "send_command", 'a "b" ; c'); assert.strictEqual(I.get(t, "account.gmail", "send_command"), 'a "b" ; c'); // A missing section is appended. t = I.set(file, "compose", "send_html", "false"); assert.ok(t.endsWith("\n[compose]\nsend_html = false\n"), JSON.stringify(t)); assert.strictEqual(I.get(t, "compose", "send_html"), "false"); // The same key in another section is untouched. t = I.set("[a]\nx = 1\n\n[b]\nx = 2\n", "b", "x", "3"); assert.strictEqual(t, "[a]\nx = 1\n\n[b]\nx = 3\n"); // remove deletes the line, where set(null) would comment it out. t = I.remove(file, "tagcolors", "shopping/amazon"); assert.deepStrictEqual(I.entries(t, "tagcolors"), []); assert.ok(!t.includes("amazon")); assert.strictEqual(I.remove(file, "tagcolors", "nope"), file); // Whole sections, for accounts. t = I.addSection(file, "account.new", [["maildir", "new"], ["trash", "Trash"]]); assert.deepStrictEqual(I.sections(t), ["general", "account.gmail", "tagcolors", "account.new"]); assert.strictEqual(I.get(t, "account.new", "trash"), "Trash"); t = I.removeSection(file, "account.gmail"); assert.deepStrictEqual(I.sections(t), ["general", "tagcolors"]); assert.strictEqual(t, "[general]\n; startup_query = Unread\ntoolbar_icon_size = 32\ndate_format = dd/MM/yyyy hh:mm\n\n[tagcolors]\nshopping/amazon = #ff9900\n"); console.log("test_ini: ok");