Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990import { describe, expect, it } from "vitest";import { decodeLogFrame, pipelineLogsUrl } from "#lib/api/spindleLogs.ts";
// captured off the spindle's own serializer: CiSubscribePipelineLogs_Event// .Serialize in api/tangled/cisubscribePipelineLogs_ext.go, hex-dumpedconst frames = { controlStart: "a261746823636f6e74726f6c626f7001a7646b696e6464757365726473746570016474696d6574323032362d30382d30365431323a30303a30305a6673746174757365737461727467636f6d6d616e64676563686f20686967636f6e74656e746952756e20746573747368776f726b666c6f77656275696c64", controlMinimal: "a261746823636f6e74726f6c626f7001a46473746570016474696d6574323032362d30382d30365431323a30303a30395a67636f6e74656e746952756e20746573747368776f726b666c6f77656275696c64", data: "a26174652364617461626f7001a56473746570016474696d6574323032362d30382d30365431323a30303a30315a6673747265616d6673746465727267636f6e74656e746e1b5b33316d626f6f6d1b5b306d0a68776f726b666c6f77656275696c64", error: "a1626f7020a2656572726f7270576f726b666c6f774e6f74466f756e64676d657373616765706e6f207375636820776f726b666c6f77"} as const;
const bytes = (hex: string): Uint8Array => Uint8Array.from(hex.match(/../g)!.map((pair) => parseInt(pair, 16)));
describe("decodeLogFrame", () => { it("reads a step start with its command and kind", () => { expect(decodeLogFrame(bytes(frames.controlStart))).toEqual({ kind: "control", control: { time: "2026-08-06T12:00:00Z", workflow: "build", step: 1, content: "Run tests", command: "echo hi", status: "start", kind: "user" } }); });
it("leaves the optional control fields off when the spindle omits them", () => { const frame = decodeLogFrame(bytes(frames.controlMinimal)); expect(frame).toEqual({ kind: "control", control: { time: "2026-08-06T12:00:09Z", workflow: "build", step: 1, content: "Run tests" } }); });
it("keeps a data line's ansi bytes and trailing newline intact", () => { expect(decodeLogFrame(bytes(frames.data))).toEqual({ kind: "data", data: { time: "2026-08-06T12:00:01Z", workflow: "build", step: 1, content: "\u001b[31mboom\u001b[0m\n", stream: "stderr" } }); });
it("surfaces the stream's error frame", () => { expect(decodeLogFrame(bytes(frames.error))).toEqual({ kind: "error", error: "WorkflowNotFound", message: "no such workflow" }); });
it("ignores a message type it doesn't know", () => { // same header shape, unknown t const unknown = "a2617464236e6577626f7001a0"; expect(decodeLogFrame(bytes(unknown))).toBeNull(); });});
describe("pipelineLogsUrl", () => { it("upgrades the spindle's scheme and repeats the workflow param", () => { expect( pipelineLogsUrl("spindle.tangled.org", "did:plc:thisrepo", "3lz", ["build", "test"]) ).toBe( "wss://spindle.tangled.org/xrpc/org.tangled.ci.subscribePipelineLogs?repo=did%3Aplc%3Athisrepo&pipeline=3lz&workflows=build&workflows=test" ); });
it("stays plaintext for a local spindle", () => { expect(pipelineLogsUrl("localhost:6555", "did:plc:thisrepo", "3lz", ["build"])).toBe( "ws://localhost:6555/xrpc/org.tangled.ci.subscribePipelineLogs?repo=did%3Aplc%3Athisrepo&pipeline=3lz&workflows=build" ); });});