mengw15 opened a new issue, #8100:
URL: https://github.com/apache/texera/issues/8100

   ### Task Summary
   
   `ComputingUnitSelectionComponent` is at **80.21 % with 51 uncovered lines 
and 24 half-taken branches**, and the bulk of that is its 
Python-virtual-environment management: creating an environment, reconciling 
saved packages against the database, installing user packages, and streaming 
pip output over a websocket. The validation guards in that area — duplicate 
environment name, missing package version, package already present as a system 
package — are never triggered.
   
   Pure EXTEND of `computing-unit-selection.component.spec.ts` (98 `it()` 
blocks already). Vitest/jsdom; see `frontend/TESTING.md` and 
`frontend/AGENTS.md`.
   
   ### Behavior to add
   
   **`ComputingUnitSelectionComponent` — PVE management** 
(`frontend/src/app/workspace/component/power-button/computing-unit-selection.component.ts`,
 codecov 80.21 % — EXTEND)
   
   - **`createVirtualEnvironment`** (948–952) — `duplicateExists` scans the 
other environments for a name clash; when it hits, 
`notificationService.error("An environment with this name already exists…")` 
fires and the method returns without creating. Cover the duplicate case (and 
confirm nothing was created) and the unique case.
   - **`installUserPackages`** (966–987) — three separate paths:
     - `missingVersionPackage` (966–971): a package with a name but no operator 
or no version triggers *"Please specify an operator and version…"* and returns. 
Cover a package missing the operator, one missing the version, and a 
fully-specified one.
     - the filter at 981–984 that keeps only packages with a non-empty trimmed 
name;
     - the system-package skip (986–987): when the lower-cased package name is 
already in `systemPackageNames`, it reports *"Skipped <name>: already installed 
as a system package"* and does not install it. Cover a name that collides 
(including a case-differing one, since the check lower-cases) and one that does 
not.
   - **`applySavedPveAsUpdate`** (709–717) — the reconciliation between the 
current environment and what the database holds. The `else if ((cur.version ?? 
"").trim() !== (db.version ?? "").trim())` arm pushes the current package onto 
`toDelete`, as does the later branch at 717. Cover: a package whose version 
matches (no deletion), one whose version differs (deletion), and one whose 
version is absent on either side so the `?? ""` fallback is taken.
   - **`parseDbPackages`** (689) and **`getPVEs`** (776) — the `match ? 
match[2] : raw ?? ""` and `(version ?? "").trim()` fallbacks; feed rows with 
and without a parseable version.
   - **`togglePackageDelete`** (607) — the `pkg.version ?? ""` fallback for a 
package with no version.
   - **`runPveWebSocket`** (889, 904) — the message path appends `event.data` 
to `currentEnv.pipOutput ?? ""`, and the error path appends `"\n[WebSocket 
error]\n"`. Cover both starting from an environment with no prior output so the 
`?? ""` fallback runs. Drive the socket by invoking the double's `onmessage` / 
`onerror` directly.
   - **`updatePrettyPipOutput`** (819) — the `env.pipOutput ?? ""` fallback.
   - **`refreshUserPackages`** (925–928) — the success path assigning 
`parsePackageRows(pkgs)` and the `error:` handler.
   - **`confirmUpdateUnitName`** (443–447) — the `if (unit)` guard and the `if 
(this.selectedComputingUnit?.computingUnit.cuid === cuid)` branch that also 
updates the selected unit. Cover renaming the selected unit and a different one.
   - **`startEditingUnitName`** (415–417) — the `if (input)` guard around 
`focus()` / `select()`; cover with the input present and absent. Spy on 
`focus`/`select`; do not assert on caret position or geometry.
   - **`registerWorkflowMetadataSubscription`** (281) — the `if (runningUnit)` 
branch.
   
   Determinism notes:
   - Stub the websocket with a fake whose handlers you invoke synchronously; 
never open a real connection and never wait on a timer.
   - Stub `notificationService`, the PVE service and the computing-unit 
service; use `of(...)` / `throwError(...)` or `HttpClientTestingModule` with 
synchronous flushes.
   - `vi.restoreAllMocks()` in `afterEach`, `fixture.destroy()` so pollers 
stop, and clone environment/package fixtures per test — these handlers mutate 
them in place.
   - Do not assert on `console.error` alone; assert on the notification message 
and the resulting state.
   
   Out of scope: the resource-formatting getters (`getCpuValue`, 
`getMemoryValue`, `getCpuUnit`, `getMemoryUnit` and friends) — #6745 proposed 
exactly those and was closed as not planned, so leave them alone here.
   
   Note #7752 is open and touches this component — rebase before finishing.
   
   ### Task Type
   
   - [ ] Refactor / Cleanup
   - [ ] DevOps / Deployment / CI
   - [x] Testing / QA
   - [ ] Documentation
   - [ ] Performance
   - [ ] Other
   


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