mirror of
https://github.com/YuzuZensai/Termix.git
synced 2026-09-14 02:59:06 +00:00
106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|||
|
|
import {
|
||
|
|
isExecutableFile,
|
||
|
|
modeToPermissions,
|
||
|
|
formatMtime,
|
||
|
|
getMimeType,
|
||
|
|
detectBinary,
|
||
|
|
} from "./file-manager-utils.js";
|
||
|
|
|
||
|
|
describe("isExecutableFile", () => {
|
||
|
|
it("flags scripts with execute permission", () => {
|
||
|
|
expect(isExecutableFile("-rwxr-xr-x", "deploy.sh")).toBe(true);
|
||
|
|
expect(isExecutableFile("-rwxr-xr-x", "run.py")).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("flags known executable extensions with execute permission", () => {
|
||
|
|
expect(isExecutableFile("-rwxr-xr-x", "tool.bin")).toBe(true);
|
||
|
|
expect(isExecutableFile("-rwxr-xr-x", "app.exe")).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("flags extensionless files with execute permission", () => {
|
||
|
|
expect(isExecutableFile("-rwxr-xr-x", "myprogram")).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("does not flag files without execute permission", () => {
|
||
|
|
expect(isExecutableFile("-rw-r--r--", "deploy.sh")).toBe(false);
|
||
|
|
expect(isExecutableFile("-rw-r--r--", "myprogram")).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("does not flag non-script data files even when executable", () => {
|
||
|
|
expect(isExecutableFile("-rwxr-xr-x", "notes.txt")).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("modeToPermissions", () => {
|
||
|
|
it("renders a regular file with rwxr-xr-x", () => {
|
||
|
|
expect(modeToPermissions(0o100755)).toBe("-rwxr-xr-x");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("renders a directory prefix", () => {
|
||
|
|
expect(modeToPermissions(0o040755)).toBe("drwxr-xr-x");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("renders a symlink prefix", () => {
|
||
|
|
expect(modeToPermissions(0o120777)).toBe("lrwxrwxrwx");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("renders a read-only file", () => {
|
||
|
|
expect(modeToPermissions(0o100444)).toBe("-r--r--r--");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("renders no permissions", () => {
|
||
|
|
expect(modeToPermissions(0o100000)).toBe("----------");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("formatMtime", () => {
|
||
|
|
it("uses HH:MM format for recent timestamps", () => {
|
||
|
|
// Within the last 6 months relative to now.
|
||
|
|
const recent = Math.floor(Date.now() / 1000) - 60 * 60 * 24 * 5;
|
||
|
|
const result = formatMtime(recent);
|
||
|
|
expect(result).toMatch(/^[A-Z][a-z]{2} +\d{1,2} \d{2}:\d{2}$/);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("uses the year for old timestamps", () => {
|
||
|
|
// ~2 years ago is comfortably outside the 6-month window.
|
||
|
|
const old = Math.floor(Date.now() / 1000) - 60 * 60 * 24 * 365 * 2;
|
||
|
|
const result = formatMtime(old);
|
||
|
|
expect(result).toMatch(/^[A-Z][a-z]{2} +\d{1,2} +\d{4}$/);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("getMimeType", () => {
|
||
|
|
it("maps known extensions", () => {
|
||
|
|
expect(getMimeType("readme.txt")).toBe("text/plain");
|
||
|
|
expect(getMimeType("data.json")).toBe("application/json");
|
||
|
|
expect(getMimeType("photo.JPEG")).toBe("image/jpeg");
|
||
|
|
expect(getMimeType("archive.zip")).toBe("application/zip");
|
||
|
|
});
|
||
|
|
|
||
|
|
it("falls back to octet-stream for unknown or missing extensions", () => {
|
||
|
|
expect(getMimeType("mystery.xyz")).toBe("application/octet-stream");
|
||
|
|
expect(getMimeType("noextension")).toBe("application/octet-stream");
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("detectBinary", () => {
|
||
|
|
it("returns false for empty buffers", () => {
|
||
|
|
expect(detectBinary(Buffer.from([]))).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns false for plain UTF-8 text", () => {
|
||
|
|
expect(detectBinary(Buffer.from("hello world\nsecond line\t tab"))).toBe(
|
||
|
|
false,
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("returns true when null bytes are present", () => {
|
||
|
|
expect(detectBinary(Buffer.from([0x48, 0x00, 0x49, 0x00]))).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("allows common whitespace control characters", () => {
|
||
|
|
expect(detectBinary(Buffer.from("line1\r\nline2\tend"))).toBe(false);
|
||
|
|
});
|
||
|
|
});
|