This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-7470-dafccec7990fb3aec6b2b07b919051eccc115176
in repository https://gitbox.apache.org/repos/asf/texera.git

commit ab4d25eb16fdd4b1b4ac74a890ea3eaba62b5e0a
Author: Meng Wang <[email protected]>
AuthorDate: Sun Aug 9 16:09:34 2026 -0700

    test(frontend): cover HuggingFaceImageUploadComponent template preview and 
error states (#7470)
    
    ### What changes were proposed in this PR?
    
    Extends `HuggingFaceImageUploadComponent`'s spec to render the template.
    The
    class file is already at 100%, but the existing tests only drive the
    handlers
    directly, so the preview panel never rendered and
    `hugging-face-image-upload.component.html` sat at ~32%.
    
    7 added tests render the component and assert on the DOM:
    
    - No preview panel while no image is selected.
    - The preview `<img>` is bound to the stored data URL (`src`, `alt`).
    - The panel's label falls back to `"Uploaded image"` when no file name
    is known, and shows the selected file name once one is.
    - The **Clear** button clears the control and removes the panel.
    - The error block renders the current `errorMessage`.
    - A `change` event with no file selected leaves the control untouched —
    this also covers the file input's `(change)` binding while staying fully
    synchronous (the guard returns before any `FileReader`/canvas work).
    
    This lifts the template from **~32% to 100% statements**. Branches land
    at 50%,
    which is the maximum reachable — see below.
    
    **The `"Selected image"` fallback is unreachable.** The issue asks for a
    test
    where `displayFileName` is empty so `{{ displayFileName || "Selected
    image" }}`
    renders the fallback, but that state cannot occur:
    
    - the panel only renders when `previewSrc` is truthy, which requires
    `hasImage`;
    - `displayFileName` returns `fileName` when set, otherwise `"Uploaded
    image"` when `hasImage` — so with `hasImage` true it is never empty.
    
    So whenever the fallback could be shown, the left-hand side is already
    truthy. I
    did not force it with a fabricated getter override, since that would
    assert a
    state the component cannot reach. If desired, the template could simply
    become
    `{{ displayFileName }}` in a follow-up — left out here because this
    change is
    test-only.
    
    **Determinism:** no fake timers and no async image pipeline in the added
    tests
    (the no-file `change` path returns synchronously); no layout/geometry
    assertions.
    No production code was changed.
    
    ### Any related issues, documentation, discussions?
    
    Closes #7467
    
    ### How was this PR tested?
    
    Extended unit tests, run locally in `frontend/`:
    
    ```
    ng test --watch=false --include 
src/app/workspace/component/hugging-face-image-upload/hugging-face-image-upload.component.spec.ts
    # Test Files 1 passed (1) | Tests 42 passed (42)   — 3 consecutive runs, 0 
flakes
    # hugging-face-image-upload.component.html: ~32% -> 100% statements
    prettier --write <spec>   # formatted
    eslint  <spec>            # clean
    ```
    
    The failure path was verified by deliberately breaking a new assertion
    and
    confirming the suite exits non-zero.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.8 [1M context])
---
 .../hugging-face-image-upload.component.spec.ts    | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git 
a/frontend/src/app/workspace/component/hugging-face-image-upload/hugging-face-image-upload.component.spec.ts
 
b/frontend/src/app/workspace/component/hugging-face-image-upload/hugging-face-image-upload.component.spec.ts
index e22a4f5715..62bac27019 100644
--- 
a/frontend/src/app/workspace/component/hugging-face-image-upload/hugging-face-image-upload.component.spec.ts
+++ 
b/frontend/src/app/workspace/component/hugging-face-image-upload/hugging-face-image-upload.component.spec.ts
@@ -18,6 +18,7 @@
  */
 
 import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { By } from "@angular/platform-browser";
 import { FormControl } from "@angular/forms";
 import { HuggingFaceImageUploadComponent } from 
"./hugging-face-image-upload.component";
 import { commonTestProviders } from "../../../common/testing/test-utils";
@@ -603,4 +604,79 @@ describe("HuggingFaceImageUploadComponent", () => {
       }
     });
   });
+
+  // ── Rendered template ──
+
+  describe("template rendering", () => {
+    const DATA_URL = "data:image/jpeg;base64,AAA";
+
+    const preview = () => 
fixture.debugElement.query(By.css(".hf-image-preview"));
+
+    /** Put the component in the "image selected" state and render it. */
+    function renderWithImage(fileName = ""): void {
+      component.fileName = fileName;
+      component.formControl.setValue(DATA_URL);
+      fixture.detectChanges();
+    }
+
+    it("renders no preview panel while no image is selected", () => {
+      expect(preview()).toBeNull();
+    });
+
+    it("renders the preview image bound to the stored data URL", () => {
+      renderWithImage();
+
+      expect(preview()).toBeTruthy();
+      const img = fixture.debugElement.query(By.css(".hf-image-preview img"));
+      expect(img.nativeElement.getAttribute("src")).toBe(DATA_URL);
+      expect(img.nativeElement.getAttribute("alt")).toBe("Uploaded Hugging 
Face task input");
+    });
+
+    it("labels the preview with the default text when no file name is known", 
() => {
+      renderWithImage();
+
+      expect(fixture.debugElement.query(By.css(".hf-image-meta 
span")).nativeElement.textContent.trim()).toBe(
+        "Uploaded image"
+      );
+    });
+
+    it("labels the preview with the selected file name once one is known", () 
=> {
+      renderWithImage("cat.png");
+
+      expect(fixture.debugElement.query(By.css(".hf-image-meta 
span")).nativeElement.textContent.trim()).toBe(
+        "cat.png"
+      );
+    });
+
+    it("the Clear button clears the image and removes the preview panel", () 
=> {
+      renderWithImage("cat.png");
+
+      fixture.debugElement.query(By.css(".hf-image-meta 
button")).triggerEventHandler("click", null);
+      fixture.detectChanges();
+
+      expect(component.formControl.value).toBe("");
+      expect(component.fileName).toBe("");
+      expect(preview()).toBeNull();
+    });
+
+    it("renders the error message when one is set", () => {
+      component.errorMessage = "Choose an image file.";
+      fixture.detectChanges();
+
+      const error = fixture.debugElement.query(By.css(".hf-image-error"));
+      expect(error).toBeTruthy();
+      expect(error.nativeElement.textContent.trim()).toBe("Choose an image 
file.");
+    });
+
+    it("a change event with no file selected leaves the control untouched", () 
=> {
+      const input = fixture.debugElement.query(By.css("input[type='file']"));
+
+      input.nativeElement.dispatchEvent(new Event("change"));
+      fixture.detectChanges();
+
+      expect(component.formControl.value).toBe("");
+      expect(component.errorMessage).toBe("");
+      expect(preview()).toBeNull();
+    });
+  });
 });

Reply via email to