import type { GitStatusLocalResult, GitStatusRemoteResult, GitStatusStreamEvent,} from "@t3tools/contracts";import { describe, expect, it, vi } from "vitest"; vi.mock("./wsTransport.ts", () => ({ WsTransport: class WsTransport { dispose = vi.fn(async () => undefined); reconnect = vi.fn(async () => undefined); request = vi.fn(); requestStream = vi.fn(); subscribe = vi.fn(() => () => undefined); },})); import { createWsRpcClient } from "./wsRpcClient.ts";import type { WsTransport } from "./wsTransport.ts"; const baseLocalStatus: GitStatusLocalResult = { isRepo: true, hasOriginRemote: true, isDefaultBranch: false, branch: "feature/demo", hasWorkingTreeChanges: false, workingTree: { files: [], insertions: 0, deletions: 0 },}; const baseRemoteStatus: GitStatusRemoteResult = { hasUpstream: true, aheadCount: 0, behindCount: 0, pr: null,}; describe("createWsRpcClient", () => { it("runs beforeReconnect before awaiting transport.reconnect", async () => { const order: string[] = []; const transport = { dispose: vi.fn(async () => undefined), reconnect: vi.fn(async () => { order.push("reconnect"); }), request: vi.fn(), requestStream: vi.fn(), subscribe: vi.fn(() => () => undefined), } satisfies Pick< WsTransport, "dispose" | "reconnect" | "request" | "requestStream" | "subscribe" >; const client = createWsRpcClient(transport as unknown as WsTransport, { beforeReconnect: () => { order.push("beforeReconnect"); }, }); await client.reconnect(); expect(order).toEqual(["beforeReconnect", "reconnect"]); }); it("reduces git status stream events into flat status snapshots", () => { const subscribe = vi.fn(<TValue>(_connect: unknown, listener: (value: TValue) => void) => { for (const event of [ { _tag: "snapshot", local: baseLocalStatus, remote: null, }, { _tag: "remoteUpdated", remote: baseRemoteStatus, }, { _tag: "localUpdated", local: { ...baseLocalStatus, hasWorkingTreeChanges: true, }, }, ] satisfies GitStatusStreamEvent[]) { listener(event as TValue); } return () => undefined; }); const transport = { dispose: vi.fn(async () => undefined), reconnect: vi.fn(async () => undefined), request: vi.fn(), requestStream: vi.fn(), subscribe, } satisfies Pick< WsTransport, "dispose" | "reconnect" | "request" | "requestStream" | "subscribe" >; const client = createWsRpcClient(transport as unknown as WsTransport); const listener = vi.fn(); client.git.onStatus({ cwd: "/repo" }, listener); expect(listener.mock.calls).toEqual([ [ { ...baseLocalStatus, hasUpstream: false, aheadCount: 0, behindCount: 0, pr: null, }, ], [ { ...baseLocalStatus, ...baseRemoteStatus, }, ], [ { ...baseLocalStatus, ...baseRemoteStatus, hasWorkingTreeChanges: true, }, ], ]); });});
import type {
GitStatusLocalResult,
GitStatusRemoteResult,
GitStatusStreamEvent,
} from "@t3tools/contracts";
import { describe, expect, it, vi } from "vitest";
vi.mock("./wsTransport.ts", () => ({
WsTransport: class WsTransport {
dispose = vi.fn(async () => undefined);
reconnect = vi.fn(async () => undefined);
request = vi.fn();
requestStream = vi.fn();
subscribe = vi.fn(() => () => undefined);
},
}));
import { createWsRpcClient } from "./wsRpcClient.ts";
import type { WsTransport } from "./wsTransport.ts";
const baseLocalStatus: GitStatusLocalResult = {
isRepo: true,
hasOriginRemote: true,
isDefaultBranch: false,
branch: "feature/demo",
hasWorkingTreeChanges: false,
workingTree: { files: [], insertions: 0, deletions: 0 },
};
const baseRemoteStatus: GitStatusRemoteResult = {
hasUpstream: true,
aheadCount: 0,
behindCount: 0,
pr: null,
};
describe("createWsRpcClient", () => {
it("runs beforeReconnect before awaiting transport.reconnect", async () => {
const order: string[] = [];
const transport = {
dispose: vi.fn(async () => undefined),
reconnect: vi.fn(async () => {
order.push("reconnect");
}),
request: vi.fn(),
requestStream: vi.fn(),
subscribe: vi.fn(() => () => undefined),
} satisfies Pick<
WsTransport,
"dispose" | "reconnect" | "request" | "requestStream" | "subscribe"
>;
const client = createWsRpcClient(transport as unknown as WsTransport, {
beforeReconnect: () => {
order.push("beforeReconnect");
},
});
await client.reconnect();
expect(order).toEqual(["beforeReconnect", "reconnect"]);
});
it("reduces git status stream events into flat status snapshots", () => {
const subscribe = vi.fn(<TValue>(_connect: unknown, listener: (value: TValue) => void) => {
for (const event of [
{
_tag: "snapshot",
local: baseLocalStatus,
remote: null,
},
{
_tag: "remoteUpdated",
remote: baseRemoteStatus,
},
{
_tag: "localUpdated",
local: {
...baseLocalStatus,
hasWorkingTreeChanges: true,
},
},
] satisfies GitStatusStreamEvent[]) {
listener(event as TValue);
}
return () => undefined;
});
const transport = {
dispose: vi.fn(async () => undefined),
reconnect: vi.fn(async () => undefined),
request: vi.fn(),
requestStream: vi.fn(),
subscribe,
} satisfies Pick<
WsTransport,
"dispose" | "reconnect" | "request" | "requestStream" | "subscribe"
>;
const client = createWsRpcClient(transport as unknown as WsTransport);
const listener = vi.fn();
client.git.onStatus({ cwd: "/repo" }, listener);
expect(listener.mock.calls).toEqual([
[
{
...baseLocalStatus,
hasUpstream: false,
aheadCount: 0,
behindCount: 0,
pr: null,
},
],
[
{
...baseLocalStatus,
...baseRemoteStatus,
},
],
[
{
...baseLocalStatus,
...baseRemoteStatus,
hasWorkingTreeChanges: true,
},
],
]);
});
});