test: add pickAsset unit tests for architecture-aware signal-cli install

This commit is contained in:
Harrington-bot
2026-02-13 13:10:48 +00:00
committed by Peter Steinberger
parent eb4a0a84f2
commit 771c7ba14e
2 changed files with 134 additions and 4 deletions

View File

@@ -0,0 +1,128 @@
import { describe, expect, it } from "vitest";
import type { ReleaseAsset } from "./signal-install.js";
import { looksLikeArchive, pickAsset } from "./signal-install.js";
// Realistic asset list modelled after an actual signal-cli GitHub release.
const SAMPLE_ASSETS: ReleaseAsset[] = [
{
name: "signal-cli-0.13.14-Linux-native.tar.gz",
browser_download_url: "https://example.com/linux-native.tar.gz",
},
{
name: "signal-cli-0.13.14-Linux-native.tar.gz.asc",
browser_download_url: "https://example.com/linux-native.tar.gz.asc",
},
{
name: "signal-cli-0.13.14-macOS-native.tar.gz",
browser_download_url: "https://example.com/macos-native.tar.gz",
},
{
name: "signal-cli-0.13.14-macOS-native.tar.gz.asc",
browser_download_url: "https://example.com/macos-native.tar.gz.asc",
},
{
name: "signal-cli-0.13.14-Windows-native.zip",
browser_download_url: "https://example.com/windows-native.zip",
},
{
name: "signal-cli-0.13.14-Windows-native.zip.asc",
browser_download_url: "https://example.com/windows-native.zip.asc",
},
{ name: "signal-cli-0.13.14.tar.gz", browser_download_url: "https://example.com/jvm.tar.gz" },
{
name: "signal-cli-0.13.14.tar.gz.asc",
browser_download_url: "https://example.com/jvm.tar.gz.asc",
},
];
describe("looksLikeArchive", () => {
it("recognises .tar.gz", () => {
expect(looksLikeArchive("foo.tar.gz")).toBe(true);
});
it("recognises .tgz", () => {
expect(looksLikeArchive("foo.tgz")).toBe(true);
});
it("recognises .zip", () => {
expect(looksLikeArchive("foo.zip")).toBe(true);
});
it("rejects signature files", () => {
expect(looksLikeArchive("foo.tar.gz.asc")).toBe(false);
});
it("rejects unrelated files", () => {
expect(looksLikeArchive("README.md")).toBe(false);
});
});
describe("pickAsset", () => {
describe("linux", () => {
it("selects the Linux-native asset on x64", () => {
const result = pickAsset(SAMPLE_ASSETS, "linux", "x64");
expect(result).toBeDefined();
expect(result!.name).toContain("Linux-native");
expect(result!.name).toMatch(/\.tar\.gz$/);
});
it("returns undefined on arm64 (triggers brew fallback)", () => {
const result = pickAsset(SAMPLE_ASSETS, "linux", "arm64");
expect(result).toBeUndefined();
});
it("returns undefined on arm (32-bit)", () => {
const result = pickAsset(SAMPLE_ASSETS, "linux", "arm");
expect(result).toBeUndefined();
});
});
describe("darwin", () => {
it("selects the macOS-native asset", () => {
const result = pickAsset(SAMPLE_ASSETS, "darwin", "arm64");
expect(result).toBeDefined();
expect(result!.name).toContain("macOS-native");
});
it("selects the macOS-native asset on x64", () => {
const result = pickAsset(SAMPLE_ASSETS, "darwin", "x64");
expect(result).toBeDefined();
expect(result!.name).toContain("macOS-native");
});
});
describe("win32", () => {
it("selects the Windows-native asset", () => {
const result = pickAsset(SAMPLE_ASSETS, "win32", "x64");
expect(result).toBeDefined();
expect(result!.name).toContain("Windows-native");
expect(result!.name).toMatch(/\.zip$/);
});
});
describe("edge cases", () => {
it("returns undefined for an empty asset list", () => {
expect(pickAsset([], "linux", "x64")).toBeUndefined();
});
it("skips assets with missing name or url", () => {
const partial: ReleaseAsset[] = [
{ name: "signal-cli.tar.gz" },
{ browser_download_url: "https://example.com/file.tar.gz" },
];
expect(pickAsset(partial, "linux", "x64")).toBeUndefined();
});
it("falls back to first archive for unknown platform", () => {
const result = pickAsset(SAMPLE_ASSETS, "freebsd" as NodeJS.Platform, "x64");
expect(result).toBeDefined();
expect(result!.name).toMatch(/\.tar\.gz$/);
});
it("never selects .asc signature files", () => {
const result = pickAsset(SAMPLE_ASSETS, "linux", "x64");
expect(result).toBeDefined();
expect(result!.name).not.toMatch(/\.asc$/);
});
});
});

View File

@@ -9,12 +9,12 @@ import { resolveBrewExecutable } from "../infra/brew.js";
import { runCommandWithTimeout } from "../process/exec.js";
import { CONFIG_DIR } from "../utils.js";
type ReleaseAsset = {
export type ReleaseAsset = {
name?: string;
browser_download_url?: string;
};
type NamedAsset = {
export type NamedAsset = {
name: string;
browser_download_url: string;
};
@@ -31,7 +31,8 @@ export type SignalInstallResult = {
error?: string;
};
function looksLikeArchive(name: string): boolean {
/** @internal Exported for testing. */
export function looksLikeArchive(name: string): boolean {
return name.endsWith(".tar.gz") || name.endsWith(".tgz") || name.endsWith(".zip");
}
@@ -43,7 +44,8 @@ function looksLikeArchive(name: string): boolean {
* returns `undefined` so the caller can fall back to a different install
* strategy (e.g. Homebrew).
*/
function pickAsset(
/** @internal Exported for testing. */
export function pickAsset(
assets: ReleaseAsset[],
platform: NodeJS.Platform,
arch: string,