mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-09 05:11:31 +00:00
99 lines
3.1 KiB
TypeScript
99 lines
3.1 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import {
|
|
isSourceChange,
|
|
pushPlugin,
|
|
resolveDevOptions,
|
|
} from "../packages/plugin-sdk/cli/commands/dev.mjs";
|
|
|
|
const cleanups: Array<() => void> = [];
|
|
|
|
afterEach(() => {
|
|
while (cleanups.length) cleanups.pop()!();
|
|
});
|
|
|
|
function json(status: number, body: unknown) {
|
|
return new Response(JSON.stringify(body), { status });
|
|
}
|
|
|
|
function tempFile(): string {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "termix-plugin-dev-"));
|
|
cleanups.push(() => fs.rmSync(dir, { recursive: true, force: true }));
|
|
const file = path.join(dir, "demo-1.0.0.tmxplug");
|
|
fs.writeFileSync(file, "archive");
|
|
return file;
|
|
}
|
|
|
|
describe("termix-plugin dev options", () => {
|
|
it("reads flags first, then the environment", () => {
|
|
expect(
|
|
resolveDevOptions(["--server", "http://a:8080/", "--key", "tmx_1"], {}),
|
|
).toEqual({ server: "http://a:8080", key: "tmx_1", once: false });
|
|
expect(
|
|
resolveDevOptions(["--once"], {
|
|
TERMIX_SERVER_URL: "http://b",
|
|
TERMIX_API_KEY: "tmx_2",
|
|
}),
|
|
).toEqual({ server: "http://b", key: "tmx_2", once: true });
|
|
expect(resolveDevOptions([], { TERMIX_API_KEY: "tmx_3" }).server).toBe(
|
|
"http://localhost:30001",
|
|
);
|
|
});
|
|
|
|
it("needs an API key", () => {
|
|
expect(() => resolveDevOptions([], {})).toThrow(/API key/);
|
|
});
|
|
|
|
it("watches sources only", () => {
|
|
expect(isSourceChange("src/frontend/index.tsx")).toBe(true);
|
|
expect(isSourceChange("README.md")).toBe(true);
|
|
expect(isSourceChange("dist/frontend.js")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("pushPlugin", () => {
|
|
it("uploads the file then installs it with the capabilities it asks for", async () => {
|
|
const fetchImpl = vi
|
|
.fn()
|
|
.mockResolvedValueOnce(
|
|
json(200, { token: "t".repeat(32), capabilities: ["kv:own"] }),
|
|
)
|
|
.mockResolvedValueOnce(
|
|
json(200, { id: "demo", version: "1.0.0", state: "active" }),
|
|
);
|
|
const { result } = await pushPlugin(
|
|
tempFile(),
|
|
{ server: "http://s", key: "tmx_k" },
|
|
fetchImpl,
|
|
);
|
|
expect(result.state).toBe("active");
|
|
|
|
const [uploadUrl, upload] = fetchImpl.mock.calls[0];
|
|
expect(uploadUrl).toBe("http://s/plugins/upload");
|
|
expect(upload.headers.Authorization).toBe("Bearer tmx_k");
|
|
expect(upload.headers["Content-Type"]).toBe("application/octet-stream");
|
|
|
|
const [installUrl, install] = fetchImpl.mock.calls[1];
|
|
expect(installUrl).toBe(
|
|
`http://s/plugins/upload/${"t".repeat(32)}/install`,
|
|
);
|
|
expect(JSON.parse(install.body)).toEqual({ capabilities: ["kv:own"] });
|
|
});
|
|
|
|
it("explains a server with developer mode off", async () => {
|
|
const fetchImpl = vi.fn().mockResolvedValue(
|
|
json(403, {
|
|
error: "Installing from a file needs developer mode",
|
|
code: "DEVELOPER_MODE_OFF",
|
|
}),
|
|
);
|
|
await expect(
|
|
pushPlugin(tempFile(), { server: "http://s", key: "tmx_k" }, fetchImpl),
|
|
).rejects.toThrow(
|
|
/403 Installing from a file needs developer mode\n.*developer mode/,
|
|
);
|
|
});
|
|
});
|