mengw15 commented on code in PR #7911:
URL: https://github.com/apache/texera/pull/7911#discussion_r3842332107
##########
frontend/src/app/workspace/service/agent/agent.service.spec.ts:
##########
@@ -689,6 +819,119 @@ describe("AgentService", () => {
FakeWebSocket.latest().onclose!({ code: 1006 });
expect(states[states.length - 1]).toBe(AgentState.UNAVAILABLE);
});
+
+ it("leaves the workflow stream alone when a snapshot carries no workflow
content", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ const states: AgentState[] = [];
+ service.getAgentStateObservable("agent-1").subscribe(s =>
states.push(s));
+ const workflows: (Workflow | null)[] = [];
+ service.getWorkflowObservable("agent-1").subscribe(w =>
workflows.push(w));
Review Comment:
Same as the thread above: each test gets a fresh `AgentService` from a fresh
`TestBed`, so a later test cannot emit into an earlier test's captured array.
Probed — the injected instance differs between two tests in one describe, and
the first test's array does not grow when the second subscribes and emits.
##########
frontend/src/app/workspace/service/agent/agent.service.spec.ts:
##########
@@ -689,6 +819,119 @@ describe("AgentService", () => {
FakeWebSocket.latest().onclose!({ code: 1006 });
expect(states[states.length - 1]).toBe(AgentState.UNAVAILABLE);
});
+
+ it("leaves the workflow stream alone when a snapshot carries no workflow
content", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ const states: AgentState[] = [];
+ service.getAgentStateObservable("agent-1").subscribe(s =>
states.push(s));
+ const workflows: (Workflow | null)[] = [];
+ service.getWorkflowObservable("agent-1").subscribe(w =>
workflows.push(w));
+
+ emit(FakeWebSocket.latest(), { type: "WsServerSnapshotEvent", state:
"GENERATING" });
+
+ expect(states[states.length - 1]).toBe(AgentState.GENERATING);
+ expect(workflows).toEqual([null]);
+ // Workflow polling stays in charge while the socket sends no content.
+ expect((service as
any).agentStateTracking.get("agent-1").wsWorkflowActive).toBe(false);
+ });
+
+ it("ignores a step event that carries no step", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ let steps: ReActStep[] = [];
+ service.getReActStepsObservable("agent-1").subscribe(s => (steps = s));
Review Comment:
Same as the thread above: each test gets a fresh `AgentService` from a fresh
`TestBed`, so a later test cannot emit into an earlier test's captured array.
Probed — the injected instance differs between two tests in one describe, and
the first test's array does not grow when the second subscribes and emits.
##########
frontend/src/app/workspace/service/agent/agent.service.spec.ts:
##########
@@ -689,6 +819,119 @@ describe("AgentService", () => {
FakeWebSocket.latest().onclose!({ code: 1006 });
expect(states[states.length - 1]).toBe(AgentState.UNAVAILABLE);
});
+
+ it("leaves the workflow stream alone when a snapshot carries no workflow
content", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ const states: AgentState[] = [];
+ service.getAgentStateObservable("agent-1").subscribe(s =>
states.push(s));
+ const workflows: (Workflow | null)[] = [];
+ service.getWorkflowObservable("agent-1").subscribe(w =>
workflows.push(w));
+
+ emit(FakeWebSocket.latest(), { type: "WsServerSnapshotEvent", state:
"GENERATING" });
+
+ expect(states[states.length - 1]).toBe(AgentState.GENERATING);
+ expect(workflows).toEqual([null]);
+ // Workflow polling stays in charge while the socket sends no content.
+ expect((service as
any).agentStateTracking.get("agent-1").wsWorkflowActive).toBe(false);
+ });
+
+ it("ignores a step event that carries no step", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ let steps: ReActStep[] = [];
+ service.getReActStepsObservable("agent-1").subscribe(s => (steps = s));
+
+ emit(FakeWebSocket.latest(), { type: "WsServerStepEvent" });
+
+ expect(steps).toEqual([]);
+ expect(service.getHeadId("agent-1")).toBeNull();
+ });
+
+ it("advances HEAD to the synthesised id when the step carries none", ()
=> {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+
+ emit(FakeWebSocket.latest(), {
+ type: "WsServerStepEvent",
+ step: { messageId: "m9", timestamp: "2026-06-11T00:00:00.000Z" },
+ });
+
+ // convertApiReActStep falls back to `${messageId}-${stepId || 0}`,
which is
+ // always a non-empty string, so a step never fails the HEAD guard.
+ expect(service.getHeadId("agent-1")).toBe("m9-0");
+ });
+
+ it("ignores a status event that carries no state", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ const states: AgentState[] = [];
+ service.getAgentStateObservable("agent-1").subscribe(s =>
states.push(s));
Review Comment:
Same as the thread above: each test gets a fresh `AgentService` from a fresh
`TestBed`, so a later test cannot emit into an earlier test's captured array.
Probed — the injected instance differs between two tests in one describe, and
the first test's array does not grow when the second subscribes and emits.
##########
frontend/src/app/workspace/service/agent/agent.service.spec.ts:
##########
@@ -689,6 +819,119 @@ describe("AgentService", () => {
FakeWebSocket.latest().onclose!({ code: 1006 });
expect(states[states.length - 1]).toBe(AgentState.UNAVAILABLE);
});
+
+ it("leaves the workflow stream alone when a snapshot carries no workflow
content", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ const states: AgentState[] = [];
+ service.getAgentStateObservable("agent-1").subscribe(s =>
states.push(s));
+ const workflows: (Workflow | null)[] = [];
+ service.getWorkflowObservable("agent-1").subscribe(w =>
workflows.push(w));
+
+ emit(FakeWebSocket.latest(), { type: "WsServerSnapshotEvent", state:
"GENERATING" });
+
+ expect(states[states.length - 1]).toBe(AgentState.GENERATING);
+ expect(workflows).toEqual([null]);
+ // Workflow polling stays in charge while the socket sends no content.
+ expect((service as
any).agentStateTracking.get("agent-1").wsWorkflowActive).toBe(false);
+ });
+
+ it("ignores a step event that carries no step", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ let steps: ReActStep[] = [];
+ service.getReActStepsObservable("agent-1").subscribe(s => (steps = s));
+
+ emit(FakeWebSocket.latest(), { type: "WsServerStepEvent" });
+
+ expect(steps).toEqual([]);
+ expect(service.getHeadId("agent-1")).toBeNull();
+ });
+
+ it("advances HEAD to the synthesised id when the step carries none", ()
=> {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+
+ emit(FakeWebSocket.latest(), {
+ type: "WsServerStepEvent",
+ step: { messageId: "m9", timestamp: "2026-06-11T00:00:00.000Z" },
+ });
+
+ // convertApiReActStep falls back to `${messageId}-${stepId || 0}`,
which is
+ // always a non-empty string, so a step never fails the HEAD guard.
+ expect(service.getHeadId("agent-1")).toBe("m9-0");
+ });
+
+ it("ignores a status event that carries no state", () => {
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ const states: AgentState[] = [];
+ service.getAgentStateObservable("agent-1").subscribe(s =>
states.push(s));
+
+ emit(FakeWebSocket.latest(), { type: "WsServerStatusEvent" });
+
+ expect(states).toEqual([AgentState.AVAILABLE]);
+ });
+
+ it("falls back to a generic notification when the error event carries no
message", () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+
+ emit(FakeWebSocket.latest(), { type: "WsServerErrorEvent" });
+
+ expect(notification.error).toHaveBeenCalledWith("Agent error
occurred");
+ expect((service as any).agents.has("agent-1")).toBe(true);
+ });
+
+ it("warns about an unrecognised message type and changes nothing", () =>
{
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+ seedAgent("agent-1");
+ service.activateAgent("agent-1");
+ const states: AgentState[] = [];
+ service.getAgentStateObservable("agent-1").subscribe(s =>
states.push(s));
+ let steps: ReActStep[] = [];
+ service.getReActStepsObservable("agent-1").subscribe(s => (steps = s));
Review Comment:
Same as the thread above: each test gets a fresh `AgentService` from a fresh
`TestBed`, so a later test cannot emit into an earlier test's captured array.
Probed — the injected instance differs between two tests in one describe, and
the first test's array does not grow when the second subscribes and emits.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]