mengw15 opened a new pull request, #7911:
URL: https://github.com/apache/texera/pull/7911

   ### What changes were proposed in this PR?
   
   Extends `agent.service.spec.ts` over the WebSocket lifecycle the issue lists 
—
   connection setup, the `handleWebSocketMessage` dispatch arms, and teardown — 
with
   15 tests. They live in the existing `websocket lifecycle and events` block 
and
   reuse its `FakeWebSocket` double; no new harness. Measured locally with
   `--coverage`:
   
   | `agent.service.ts` | Before | After |
   | --- | --- | --- |
   | lines | 301/329 (91.49 %) | **306/329 (93.01 %)** |
   | branches | 147/186 (79.03 %) | **160/186 (86.02 %)** |
   | functions | 90/103 | **91/103** |
   
   **Connection setup (`startStatePolling`)**
   
   - The `wss:`/`ws:` ternary (411): `window.location` is swapped for one test 
with
     the `withLocation` helper `virtual-environment.service.spec.ts` already 
uses
     (jsdom's own is not writable), and the URL the double was constructed with 
is
     asserted in full. The `ws:` side was already covered.
   - The parse-failure path (424): a payload that is not JSON is logged and 
does not
     throw out of the handler; the connection is left intact.
   - The `onerror` handler (428-429), previously an uncalled function.
   - The close guard (435), both ways: a stale socket that reports an abnormal 
close
     after being swapped out must not clear the newer connection or flip the 
state.
   
   **Message dispatch (`handleWebSocketMessage`)**
   
   - `message.workflowContent` (466) — a snapshot with no workflow content 
leaves the
     workflow stream and `wsWorkflowActive` alone, so DB polling stays in 
charge.
   - `message.step` (478) — a step event with no step changes nothing.
   - `message.state` (517) — a status event with no state changes nothing.
   - The error arm (534) — an event with no `error` falls back to
     `"Agent error occurred"`; the explicit-message side was already covered.
   - The `default` arm (451/539) — an unrecognised type warns and changes 
nothing.
   
   **Teardown**
   
   - `stopStatePolling` (548) both ways, through `deleteAgent`: for a tracked 
agent
     the socket is closed and `stopPolling$` completes; for an id that was never
     tracked it is a no-op.
   - `activateAgent` (580) — an already-open socket is kept (no second socket) 
and a
     socket that is no longer `OPEN` is replaced. `deactivateAgent` always 
clears the
     socket, so the inactive-but-still-connected shape this guard defends 
against is
     set up directly on the tracking entry, with a comment saying so.
   - `deactivateAgent` (594-606) — both early returns (unknown agent; already
     inactive) and the no-socket side of the close branch, reached the ordinary 
way
     by letting a normal close event drop the socket first.
   
   **One arm is not reachable.** The issue asks for a step "that does not" 
carry an
   id (498). `convertApiReActStep` returns
   ``id: apiStep.id || `${apiStep.messageId}-${apiStep.stepId || 0}` `` — the 
fallback
   is a template literal, which always yields a non-empty string, so
   `convertedStep.id` is never falsy and `if (convertedStep.id)` cannot take 
its else
   branch. The test covers the fallback side instead (a step with no id still
   advances HEAD to `m9-0`) and records why the arm stays half-taken. The 
remaining
   uncovered lines are the state accessors and HTTP failure paths, which #7908
   covers; the two PRs touch disjoint regions of the file.
   
   No production code was changed.
   
   ### Any related issues, documentation, discussions?
   
   Closes #7888.
   
   ### How was this PR tested?
   
   `ng test --watch=false --include 
src/app/workspace/service/agent/agent.service.spec.ts`
   — 62 passed (47 before, 15 new), repeated 3× for stability. `yarn format:ci` 
clean.
   Failure path verified by breaking one assertion in each of the 15 new tests: 
16
   failed (the 15 plus one pre-existing test that shares the mutated assertion),
   non-zero exit, then restored to green.
   
   Determinism: every socket event is delivered by invoking the double's
   `onmessage`/`onerror`/`onclose` directly — no real socket, no reconnect 
timer, and
   no new `vi.useFakeTimers()`. `withLocation` restores `window.location` in a
   `finally`, and `vi.restoreAllMocks()` was added to the block's `afterEach` 
so the
   `console` spies cannot leak into a later test even if an assertion throws.
   
   ### Was this PR authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Opus 4.8 [1M context])
   


-- 
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]

Reply via email to