Files
margin-mail/src/screens/format.test.ts
T
pj eb59cb5f8d build the app, and ship it on Linux and Windows as well as macOS
The client itself: the sync engine and mirror, the Gmail and IMAP providers,
the screener, the three boxes and two piles, compose and send, the sanitiser
and tracker stripping, contacts, clips, backup, notifications and the guide.

The pipeline that ships it. Three runners now build in parallel and the
publish gate wants all four platform keys in latest.json before a release
leaves draft. Linux gets two more packages Tauri does not build: a flatpak
repackaged from the deb against GNOME 48, and a Nix package that relinks the
deb against nixpkgs so it runs as a native Wayland client rather than through
Xwayland. CI runs the Rust suite on all three desktops rather than on Linux
alone, and rebuilds the flatpak manifest on every push to main.

Two things that were only ever exercised on macOS and were wrong everywhere
else. The menu bar was built by adjusting the submenus macOS is given, so on
a platform whose default menu has no File or View the new File menu landed
after Edit, Check for Updates landed nowhere, and the three places and the
reading pane had no menu at all. The deb declared libwebkit2gtk-4.1-0 and
libgtk-3-0 twice, because tauri.conf.json named the dependencies Tauri
already emits.

The updater key exists now, so releases can sign their artifacts.
2026-09-06 12:15:30 +05:30

65 lines
2.6 KiB
TypeScript

// The pure half of what the screens print. These are the functions with a right answer rather than
// a look, so they are asserted here instead of in the browser suite.
//
// `format.ts` reaches for a DOMParser in `previewOf` and for the binding table in `cap`, and it
// does both at call time, so importing the module in node is safe and the rest of it can be tested
// without a document.
import { describe, expect, it } from "vitest";
import { displayName, participantLine } from "./format";
describe("participantLine", () => {
it("says nothing about nobody", () => {
expect(participantLine([], false)).toBe("");
});
it("names one person as themselves", () => {
expect(participantLine(["City Power"], false)).toBe("City Power");
});
it("puts you last, and only when you wrote in the thread", () => {
expect(participantLine(["Arun Kulkarni"], true)).toBe("Arun Kulkarni and you");
expect(participantLine(["Arun Kulkarni"], false)).toBe("Arun Kulkarni");
});
it("joins up to four in full, because a count would be longer than the name", () => {
expect(participantLine(["Arun", "Maya", "Karthik", "Priya"], false)).toBe(
"Arun, Maya, Karthik and Priya",
);
expect(participantLine(["Arun", "Maya", "Karthik"], true)).toBe("Arun, Maya, Karthik and you");
});
it("names three of a crowd and counts the rest", () => {
const forty = Array.from({ length: 40 }, (_, i) => `Person ${i + 1}`);
expect(participantLine(forty, false)).toBe("Person 1, Person 2, Person 3 and 37 others");
});
it("counts you among the others rather than losing the count to you", () => {
const forty = Array.from({ length: 40 }, (_, i) => `Person ${i + 1}`);
expect(participantLine(forty, true)).toBe("Person 1, Person 2, Person 3 and 38 others");
});
it("never runs past a line, however many people are in the thread", () => {
const many = Array.from({ length: 400 }, (_, i) => `Somebody With A Long Name ${i}`);
expect(participantLine(many, true).length).toBeLessThan(120);
});
});
describe("displayName", () => {
it("reads a sorting key back the way it was written", () => {
expect(displayName({ name: "Young, Russell", address: "[email protected]" })).toBe("Russell Young");
});
it("leaves a name with two commas alone, because it is not a sorting key", () => {
expect(displayName({ name: "Beale, Jones and Fry, LLP", address: "[email protected]" })).toBe(
"Beale, Jones and Fry, LLP",
);
});
it("falls back to the address when there is no name", () => {
expect(displayName({ name: null, address: "[email protected]" })).toBe(
"[email protected]",
);
});
});