fix: 保持纯 Kafka Trace 终态展开
This commit is contained in:
+1
-1
@@ -372,7 +372,7 @@ lanes:
|
||||
secretPlaneRef: config/hwlab-v03/secrets.yaml#secretPlane
|
||||
workbench:
|
||||
traceTimeline:
|
||||
autoExpandRunning: false
|
||||
autoExpandRunning: true
|
||||
autoCollapseTerminal: false
|
||||
rawHwlabEventWindow:
|
||||
enabled: true
|
||||
|
||||
@@ -16,6 +16,71 @@ describe("TraceTimeline sequence authority", () => {
|
||||
Object.defineProperty(HTMLElement.prototype, "scrollTo", { configurable: true, value: () => undefined });
|
||||
});
|
||||
|
||||
it("auto-opens a running Trace without persisting programmatic state", async () => {
|
||||
const storageKey = "trace-lifecycle.running";
|
||||
const wrapper = mount(TraceTimeline, {
|
||||
props: {
|
||||
autoExpanded: true,
|
||||
storageKey,
|
||||
trace: liveTrace("running")
|
||||
}
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.get<HTMLDetailsElement>(".trace-disclosure").element.open).toBe(true);
|
||||
expect(window.localStorage.getItem(storageKey)).toBeNull();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("keeps an auto-opened Trace expanded when terminal policy has no collapse request", async () => {
|
||||
const wrapper = mount(TraceTimeline, {
|
||||
props: {
|
||||
autoExpanded: true,
|
||||
storageKey: "trace-lifecycle.keep-open",
|
||||
trace: liveTrace("running")
|
||||
}
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.get<HTMLDetailsElement>(".trace-disclosure").element.open).toBe(true);
|
||||
|
||||
await wrapper.setProps({ autoExpanded: null, trace: liveTrace("completed") });
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.get<HTMLDetailsElement>(".trace-disclosure").element.open).toBe(true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("collapses on an explicit terminal request while keeping a manual stored value authoritative", async () => {
|
||||
const storageKey = "trace-lifecycle.collapse";
|
||||
const wrapper = mount(TraceTimeline, {
|
||||
props: {
|
||||
autoExpanded: true,
|
||||
storageKey,
|
||||
trace: liveTrace("running")
|
||||
}
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.get<HTMLDetailsElement>(".trace-disclosure").element.open).toBe(true);
|
||||
|
||||
await wrapper.setProps({ autoExpanded: false, trace: liveTrace("completed") });
|
||||
await nextTick();
|
||||
expect(wrapper.get<HTMLDetailsElement>(".trace-disclosure").element.open).toBe(false);
|
||||
wrapper.unmount();
|
||||
|
||||
window.localStorage.setItem(storageKey, "1");
|
||||
const storedWrapper = mount(TraceTimeline, {
|
||||
props: {
|
||||
autoExpanded: false,
|
||||
storageKey,
|
||||
trace: liveTrace("completed")
|
||||
}
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
expect(storedWrapper.get<HTMLDetailsElement>(".trace-disclosure").element.open).toBe(true);
|
||||
storedWrapper.unmount();
|
||||
});
|
||||
|
||||
it("renders sourceSeq-only live Kafka rows while terminal and does not label them projected", async () => {
|
||||
const wrapper = mount(TraceTimeline, {
|
||||
props: {
|
||||
@@ -70,6 +135,16 @@ describe("TraceTimeline sequence authority", () => {
|
||||
});
|
||||
});
|
||||
|
||||
function liveTrace(status: "running" | "completed") {
|
||||
return {
|
||||
traceId: "trc_live_lifecycle",
|
||||
eventSource: "hwlab-kafka-sse" as const,
|
||||
status,
|
||||
eventCount: 1,
|
||||
events: [{ sourceEventId: "evt_live_lifecycle", runId: "run_live", sourceSeq: 1, source: "agentrun.kafka", type: "assistant", label: "agentrun:assistant:message", message: "live answer" }]
|
||||
};
|
||||
}
|
||||
|
||||
class FakeResizeObserver {
|
||||
observe(): void {}
|
||||
unobserve(): void {}
|
||||
|
||||
@@ -46,10 +46,30 @@ watch(() => [eventCount.value, props.trace?.status, readableRows.value.length, e
|
||||
void keepBottomAfterUpdate();
|
||||
});
|
||||
|
||||
watch(() => [props.trace?.traceId, props.storageKey, props.defaultExpanded, props.autoExpanded] as const, () => {
|
||||
setExpandedProgrammatically(readStoredExpanded() ?? props.autoExpanded ?? props.defaultExpanded ?? false);
|
||||
watch(() => [traceExpansionScope(), props.defaultExpanded, props.autoExpanded] as const, (current, previous) => {
|
||||
const stored = readStoredExpanded();
|
||||
if (stored !== null) {
|
||||
setExpandedProgrammatically(stored);
|
||||
return;
|
||||
}
|
||||
|
||||
const [scope, defaultExpanded, autoExpanded] = current;
|
||||
if (!previous || scope !== previous[0]) {
|
||||
setExpandedProgrammatically(autoExpanded ?? defaultExpanded ?? false);
|
||||
return;
|
||||
}
|
||||
if (typeof autoExpanded === "boolean") {
|
||||
setExpandedProgrammatically(autoExpanded);
|
||||
return;
|
||||
}
|
||||
if (defaultExpanded !== previous[1]) setExpandedProgrammatically(defaultExpanded ?? false);
|
||||
}, { immediate: true });
|
||||
|
||||
function traceExpansionScope(): string {
|
||||
if (props.storageKey) return `storage:${props.storageKey}`;
|
||||
return `trace:${String(props.trace?.traceId ?? "")}`;
|
||||
}
|
||||
|
||||
function rowKey(row: TraceEventRow, index: number): string {
|
||||
return `${row.rowId}-${row.sequenceAuthority}-${row.seq ?? "no-seq"}-${index}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user