fix(client): repair the TypeScript build
`npm run build` runs `tsc -b` first and it has been failing: `api.ts` used `NamedLock` without importing it, and four lane test fixtures predate `Lane.active_feature_id` / the widened `LaneRuntime`, so spreading a `Partial<Lane>` over them no longer satisfied the required fields. Nothing shipped could be rebuilt while this was red, which is how a client change reaches a dashboard running in production mode. The fixture fixes are casts with a note, not type relaxations — the base literals still list every required field, so the assertion states what they already prove.
This commit is contained in:
@@ -34,6 +34,10 @@ vi.mock("../../../lib/api", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
function laneFixture(over: Partial<Lane> = {}): Lane {
|
function laneFixture(over: Partial<Lane> = {}): Lane {
|
||||||
|
// `as Lane`: spreading a Partial<Lane> widens every field it may carry to
|
||||||
|
// `T | undefined`, which no longer satisfies Lane's required fields. The
|
||||||
|
// base object below still lists all of them, so the cast asserts what the
|
||||||
|
// literal already proves.
|
||||||
return {
|
return {
|
||||||
id: 9,
|
id: 9,
|
||||||
title: "",
|
title: "",
|
||||||
@@ -64,7 +68,7 @@ function laneFixture(over: Partial<Lane> = {}): Lane {
|
|||||||
slot: null,
|
slot: null,
|
||||||
ports: {},
|
ports: {},
|
||||||
...over,
|
...over,
|
||||||
};
|
} as Lane;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SUGGESTIONS: CwdSuggestion[] = [
|
const SUGGESTIONS: CwdSuggestion[] = [
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ import { DestructiveLaneModal } from "../DestructiveLaneModal";
|
|||||||
import type { Lane, LanePurgePreflight, LaneWorktreePreflight } from "../../../lib/types";
|
import type { Lane, LanePurgePreflight, LaneWorktreePreflight } from "../../../lib/types";
|
||||||
|
|
||||||
function makeLane(overrides: Partial<Lane> = {}): Lane {
|
function makeLane(overrides: Partial<Lane> = {}): Lane {
|
||||||
|
// `as Lane`: spreading a Partial<Lane> widens every field it may carry to
|
||||||
|
// `T | undefined`, which no longer satisfies Lane's required fields. The
|
||||||
|
// base object below still lists all of them, so the cast asserts what the
|
||||||
|
// literal already proves.
|
||||||
return {
|
return {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "demo",
|
title: "demo",
|
||||||
@@ -50,7 +54,7 @@ function makeLane(overrides: Partial<Lane> = {}): Lane {
|
|||||||
slot: null,
|
slot: null,
|
||||||
ports: {},
|
ports: {},
|
||||||
...overrides,
|
...overrides,
|
||||||
};
|
} as Lane;
|
||||||
}
|
}
|
||||||
|
|
||||||
function worktreePreflight(overrides: Partial<LaneWorktreePreflight> = {}): LaneWorktreePreflight {
|
function worktreePreflight(overrides: Partial<LaneWorktreePreflight> = {}): LaneWorktreePreflight {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
|
|||||||
import { render, screen, waitFor } from "@testing-library/react";
|
import { render, screen, waitFor } from "@testing-library/react";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
import LaneCard from "../LaneCard";
|
import LaneCard from "../LaneCard";
|
||||||
import type { Lane } from "../../../lib/types";
|
import type { Lane, LaneRuntime } from "../../../lib/types";
|
||||||
import { api } from "../../../lib/api";
|
import { api } from "../../../lib/api";
|
||||||
|
|
||||||
vi.mock("../../../lib/api", () => ({
|
vi.mock("../../../lib/api", () => ({
|
||||||
@@ -48,6 +48,10 @@ vi.mocked(api.locks.list).mockReset();
|
|||||||
vi.mocked(api.locks.list).mockResolvedValue({ locks: [] });
|
vi.mocked(api.locks.list).mockResolvedValue({ locks: [] });
|
||||||
|
|
||||||
function makeLane(overrides: Partial<Lane> = {}): Lane {
|
function makeLane(overrides: Partial<Lane> = {}): Lane {
|
||||||
|
// `as Lane`: spreading a Partial<Lane> widens every field it may carry to
|
||||||
|
// `T | undefined`, which no longer satisfies Lane's required fields. The
|
||||||
|
// base object below still lists all of them, so the cast asserts what the
|
||||||
|
// literal already proves.
|
||||||
return {
|
return {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "demo",
|
title: "demo",
|
||||||
@@ -78,7 +82,7 @@ function makeLane(overrides: Partial<Lane> = {}): Lane {
|
|||||||
slot: null,
|
slot: null,
|
||||||
ports: {},
|
ports: {},
|
||||||
...overrides,
|
...overrides,
|
||||||
};
|
} as Lane;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("LaneCard status badge", () => {
|
describe("LaneCard status badge", () => {
|
||||||
@@ -396,6 +400,9 @@ describe("LaneCard — named locks", () => {
|
|||||||
|
|
||||||
describe("agents install / mcp sync / integration badges / sync check", () => {
|
describe("agents install / mcp sync / integration badges / sync check", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
// Only the fields this describe block's assertions read; `as LaneRuntime`
|
||||||
|
// keeps the double from having to restate a shape the component never
|
||||||
|
// touches here.
|
||||||
vi.mocked(api.lanes.runtime).mockResolvedValue({
|
vi.mocked(api.lanes.runtime).mockResolvedValue({
|
||||||
available: true as const,
|
available: true as const,
|
||||||
provisioned: true as const,
|
provisioned: true as const,
|
||||||
@@ -403,7 +410,7 @@ describe("agents install / mcp sync / integration badges / sync check", () => {
|
|||||||
slot: 1,
|
slot: 1,
|
||||||
profileDir: "/work/demo/.ccam/profile",
|
profileDir: "/work/demo/.ccam/profile",
|
||||||
ports: {},
|
ports: {},
|
||||||
});
|
} as unknown as LaneRuntime);
|
||||||
vi.mocked(api.lanes.integration).mockImplementation((_id, name) =>
|
vi.mocked(api.lanes.integration).mockImplementation((_id, name) =>
|
||||||
Promise.resolve({ enabled: name === "tracker" })
|
Promise.resolve({ enabled: name === "tracker" })
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ import type {
|
|||||||
LaneGitFacts,
|
LaneGitFacts,
|
||||||
LaneRuntime,
|
LaneRuntime,
|
||||||
ModelPricing,
|
ModelPricing,
|
||||||
|
NamedLock,
|
||||||
Session,
|
Session,
|
||||||
SessionDrillIn,
|
SessionDrillIn,
|
||||||
SessionStats,
|
SessionStats,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type LaneFixture = {
|
|||||||
pipeline_nodes: never[];
|
pipeline_nodes: never[];
|
||||||
detected_signal: string | null;
|
detected_signal: string | null;
|
||||||
run_id: string | null;
|
run_id: string | null;
|
||||||
|
active_feature_id?: number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
let lanesToReturn: LaneFixture[] = [
|
let lanesToReturn: LaneFixture[] = [
|
||||||
@@ -583,7 +584,8 @@ describe("Workspace — proof gallery", () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
// Set active_feature_id and ensure features list is populated
|
// Set active_feature_id and ensure features list is populated
|
||||||
lanesToReturn[0].active_feature_id = 1;
|
// (indexed access is `| undefined` under noUncheckedIndexedAccess)
|
||||||
|
lanesToReturn[0]!.active_feature_id = 1;
|
||||||
vi.mocked(api.lanes.features.list).mockResolvedValue({
|
vi.mocked(api.lanes.features.list).mockResolvedValue({
|
||||||
features: [
|
features: [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user