POST /farms/:id/printers now takes any of the four vendors the gateway can drive. Credentials depend on the vendor: Bambu needs an access code and serial, OctoPrint and PrusaLink an API key, Klipper nothing. A missing one is a 422 naming what is needed. The API key is relayed to the gateway and kept out of logs and errors like the access code. The printer_vendor enum gains octoprint (migration 0006); PrusaLink is stored as prusa, the name the enum already had. scripts/e2e-vendors.sh adds each kind through the API against a fake REST printer (scripts/fake-http-printer.ts) and runs a job through the real scheduler to completion. The fake shares its author's reading of the docs with the driver, so this proves the plumbing, not the protocols.
59 lines
2.6 KiB
TypeScript
59 lines
2.6 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { dbVendorFor, gatewayIdFor, missingCredential, safeGatewayError } from "../src/provision/plan";
|
|
|
|
describe("gatewayIdFor", () => {
|
|
const accepted = /^[A-Za-z0-9_-]{1,64}$/;
|
|
|
|
test("makes a readable id the gateway will accept", () => {
|
|
expect(gatewayIdFor("Bench P1P", () => 0)).toBe("bench-p1p-0000");
|
|
expect(gatewayIdFor("Bench P1P", () => 0.999999)).toMatch(accepted);
|
|
});
|
|
|
|
test("survives names with nothing usable in them", () => {
|
|
expect(gatewayIdFor("***", () => 0.5)).toMatch(/^printer-[0-9a-f]{4}$/);
|
|
expect(gatewayIdFor("Принтер", () => 0.5)).toMatch(accepted);
|
|
});
|
|
|
|
test("never exceeds what the gateway accepts, whatever the name", () => {
|
|
expect(gatewayIdFor("x".repeat(500))).toMatch(accepted);
|
|
expect(gatewayIdFor("../../etc/passwd")).toMatch(accepted);
|
|
});
|
|
|
|
test("two printers with the same name get different ids", () => {
|
|
const ids = new Set(Array.from({ length: 50 }, () => gatewayIdFor("Same name")));
|
|
expect(ids.size).toBeGreaterThan(30);
|
|
});
|
|
});
|
|
|
|
describe("safeGatewayError", () => {
|
|
test("passes an ordinary message through", () => {
|
|
expect(safeGatewayError("could not connect to the printer", ["12345678"])).toBe(
|
|
"could not connect to the printer",
|
|
);
|
|
});
|
|
test("removes a credential that somehow got into the message", () => {
|
|
expect(safeGatewayError("bad login 12345678 for host", ["12345678"])).toBe("bad login <hidden> for host");
|
|
});
|
|
test("has an answer when the gateway gave none", () => {
|
|
expect(safeGatewayError(undefined, [])).toBe("the gateway did not say why");
|
|
});
|
|
});
|
|
|
|
describe("missingCredential", () => {
|
|
test("a Bambu needs its access code and serial number", () => {
|
|
expect(missingCredential("bambu", {})).toBe("an access code");
|
|
expect(missingCredential("bambu", { accessCode: "12345678" })).toBe("a serial number");
|
|
expect(missingCredential("bambu", { accessCode: "12345678", serialNumber: "01P00A123" })).toBeUndefined();
|
|
});
|
|
test("OctoPrint and PrusaLink need an API key; Klipper needs nothing", () => {
|
|
expect(missingCredential("octoprint", { accessCode: "x" })).toBe("an API key");
|
|
expect(missingCredential("prusa_link", { apiKey: " " })).toBe("an API key");
|
|
expect(missingCredential("prusa_link", { apiKey: "k" })).toBeUndefined();
|
|
expect(missingCredential("klipper", {})).toBeUndefined();
|
|
});
|
|
test("the gateway's PrusaLink is stored under the database's older name", () => {
|
|
expect(dbVendorFor("prusa_link")).toBe("prusa");
|
|
expect(dbVendorFor("octoprint")).toBe("octoprint");
|
|
});
|
|
});
|