fix: hide unknown activity state in inspector
This commit is contained in:
parent
8d8fb42a94
commit
60bb0ef064
|
|
@ -173,7 +173,7 @@ describe("SessionInspector Activity section", () => {
|
||||||
it.each([
|
it.each([
|
||||||
["idle", "Idle"],
|
["idle", "Idle"],
|
||||||
["active", "Working"],
|
["active", "Working"],
|
||||||
["waiting_input", "Input needed"],
|
["waiting_input", "Input Needed"],
|
||||||
["exited", "Exited"],
|
["exited", "Exited"],
|
||||||
] as const)("renders %s from raw session activity", (state, label) => {
|
] as const)("renders %s from raw session activity", (state, label) => {
|
||||||
renderWithQuery(
|
renderWithQuery(
|
||||||
|
|
@ -188,6 +188,40 @@ describe("SessionInspector Activity section", () => {
|
||||||
expect(activitySection().getByText(label)).toBeInTheDocument();
|
expect(activitySection().getByText(label)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("renders unknown activity as unavailable instead of leaking the internal enum", () => {
|
||||||
|
renderWithQuery(
|
||||||
|
<SessionInspector
|
||||||
|
session={session([], {
|
||||||
|
status: "working",
|
||||||
|
activity: { state: "unknown", lastActivityAt: "2026-06-15T10:00:00Z" },
|
||||||
|
})}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(activitySection().getByText("Activity Unavailable")).toBeInTheDocument();
|
||||||
|
expect(activitySection().queryByText("Unknown")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to unavailable when no activity has been reported", () => {
|
||||||
|
renderWithQuery(<SessionInspector session={session([], { status: "working" })} />);
|
||||||
|
|
||||||
|
expect(activitySection().getByText("Activity Unavailable")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps the last known activity visible when the daemon reports no signal", () => {
|
||||||
|
renderWithQuery(
|
||||||
|
<SessionInspector
|
||||||
|
session={session([], {
|
||||||
|
status: "no_signal",
|
||||||
|
activity: { state: "idle", lastActivityAt: "2026-06-15T10:00:00Z" },
|
||||||
|
})}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const activityRow = activitySection().getByText("Idle").closest(".inspector-timeline__ev") as HTMLElement;
|
||||||
|
expect(within(activityRow).getByText("No Signal")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it("does not derive the Activity label from PR-oriented session status", () => {
|
it("does not derive the Activity label from PR-oriented session status", () => {
|
||||||
renderWithQuery(
|
renderWithQuery(
|
||||||
<SessionInspector
|
<SessionInspector
|
||||||
|
|
@ -199,12 +233,12 @@ describe("SessionInspector Activity section", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(activitySection().getByText("Idle")).toBeInTheDocument();
|
expect(activitySection().getByText("Idle")).toBeInTheDocument();
|
||||||
expect(activitySection().queryByText("Input needed")).not.toBeInTheDocument();
|
expect(activitySection().queryByText("Input Needed")).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
["ci_failed", "CI failed"],
|
["ci_failed", "CI Failed"],
|
||||||
["changes_requested", "Changes requested"],
|
["changes_requested", "Changes Requested"],
|
||||||
] as const)("renders %s as an SCM state in the current Activity row", (status, label) => {
|
] as const)("renders %s as an SCM state in the current Activity row", (status, label) => {
|
||||||
renderWithQuery(
|
renderWithQuery(
|
||||||
<SessionInspector
|
<SessionInspector
|
||||||
|
|
@ -265,8 +299,8 @@ describe("SessionInspector Activity section", () => {
|
||||||
expect(activitySection().getByText("Opened")).toBeInTheDocument();
|
expect(activitySection().getByText("Opened")).toBeInTheDocument();
|
||||||
expect(activitySection().getByText("PR #7")).toBeInTheDocument();
|
expect(activitySection().getByText("PR #7")).toBeInTheDocument();
|
||||||
const activityRow = activitySection().getByText("Idle").closest(".inspector-timeline__ev") as HTMLElement;
|
const activityRow = activitySection().getByText("Idle").closest(".inspector-timeline__ev") as HTMLElement;
|
||||||
expect(within(activityRow).getByText("CI failed")).toBeInTheDocument();
|
expect(within(activityRow).getByText("CI Failed")).toBeInTheDocument();
|
||||||
expect(within(activityRow).getByText("Changes requested")).toBeInTheDocument();
|
expect(within(activityRow).getByText("Changes Requested")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("orders timeline milestones around the combined current state row", () => {
|
it("orders timeline milestones around the combined current state row", () => {
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,11 @@ function ActivityTimeline({ session }: { session: WorkspaceSession }) {
|
||||||
<span className="inspector-timeline__badge">
|
<span className="inspector-timeline__badge">
|
||||||
<InspectorActivityPill state={session.activity?.state ?? "unknown"} />
|
<InspectorActivityPill state={session.activity?.state ?? "unknown"} />
|
||||||
</span>
|
</span>
|
||||||
|
{session.status === "no_signal" ? (
|
||||||
|
<span className="inspector-timeline__badge">
|
||||||
|
<TimelinePill {...ACTIVITY_WARNING_PILL.no_signal} />
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
{scmTimelineStates(session).map((state) => (
|
{scmTimelineStates(session).map((state) => (
|
||||||
<span key={state} className="inspector-timeline__badge">
|
<span key={state} className="inspector-timeline__badge">
|
||||||
<InspectorScmPill state={state} />
|
<InspectorScmPill state={state} />
|
||||||
|
|
@ -352,16 +357,20 @@ function ActivityTimeline({ session }: { session: WorkspaceSession }) {
|
||||||
const ACTIVITY_PILL: Record<SessionActivityState, { label: string; tone: string; breathe: boolean }> = {
|
const ACTIVITY_PILL: Record<SessionActivityState, { label: string; tone: string; breathe: boolean }> = {
|
||||||
active: { label: "Working", tone: "var(--orange)", breathe: true },
|
active: { label: "Working", tone: "var(--orange)", breathe: true },
|
||||||
idle: { label: "Idle", tone: "var(--fg-muted)", breathe: false },
|
idle: { label: "Idle", tone: "var(--fg-muted)", breathe: false },
|
||||||
waiting_input: { label: "Input needed", tone: "var(--amber)", breathe: false },
|
waiting_input: { label: "Input Needed", tone: "var(--amber)", breathe: false },
|
||||||
exited: { label: "Exited", tone: "var(--fg-muted)", breathe: false },
|
exited: { label: "Exited", tone: "var(--fg-muted)", breathe: false },
|
||||||
unknown: { label: "Unknown", tone: "var(--fg-muted)", breathe: false },
|
unknown: { label: "Activity Unavailable", tone: "var(--fg-muted)", breathe: false },
|
||||||
|
};
|
||||||
|
|
||||||
|
const ACTIVITY_WARNING_PILL: Record<"no_signal", { label: string; tone: string; breathe: boolean }> = {
|
||||||
|
no_signal: { label: "No Signal", tone: "var(--fg-muted)", breathe: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
type ScmTimelineState = "ci_failed" | "changes_requested" | "conflict";
|
type ScmTimelineState = "ci_failed" | "changes_requested" | "conflict";
|
||||||
|
|
||||||
const SCM_PILL: Record<ScmTimelineState, { label: string; tone: string; breathe: boolean }> = {
|
const SCM_PILL: Record<ScmTimelineState, { label: string; tone: string; breathe: boolean }> = {
|
||||||
ci_failed: { label: "CI failed", tone: "var(--red)", breathe: false },
|
ci_failed: { label: "CI Failed", tone: "var(--red)", breathe: false },
|
||||||
changes_requested: { label: "Changes requested", tone: "var(--amber)", breathe: false },
|
changes_requested: { label: "Changes Requested", tone: "var(--amber)", breathe: false },
|
||||||
conflict: { label: "Conflict", tone: "var(--red)", breathe: false },
|
conflict: { label: "Conflict", tone: "var(--red)", breathe: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue