Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
[src]="previewSrc"
alt="Uploaded Hugging Face task input" />
<div class="hf-image-meta">
<span>{{ displayFileName || "Selected image" }}</span>
<span>{{ displayFileName }}</span>
<button
nz-button
nzSize="small"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,34 @@ describe("HuggingFaceImageUploadComponent", () => {
});
});

describe("rendered preview label", () => {
const previewLabel = () => fixture.nativeElement.querySelector(".hf-image-meta span") as HTMLElement | null;

it("labels the preview 'Uploaded image' when an image has no filename", () => {
component.formControl.setValue("data:image/jpeg;base64,AAA");
fixture.detectChanges();

expect(previewLabel()?.textContent?.trim()).toBe("Uploaded image");
});

it("labels the preview with the filename once one is known", () => {
component.formControl.setValue("data:image/jpeg;base64,AAA");
component.fileName = "cat.jpg";
fixture.detectChanges();

expect(previewLabel()?.textContent?.trim()).toBe("cat.jpg");
});

it("renders no preview at all without an image, so the label is never empty", () => {
// The preview only renders while previewSrc is non-empty, which happens exactly
// when hasImage is true — and displayFileName is never empty in that case.
component.formControl.setValue("");
fixture.detectChanges();

expect(previewLabel()).toBeNull();
});
});

// ── Shared mocking helpers ──────────────────────────────────────────────
// These helpers let us drive the private compressImage / renderCompressedDataUrl
// pipeline end-to-end through onFileSelected.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,30 @@ describe("DragDropService", () => {
expect(() => (dragDropService as any).clearEdgeIntersectionHighlight(link)).not.toThrow();
expect((dragDropService as any).findIntersectedLink({ x: 0, y: 0 })).toBeNull();
});

it("skips links that are in the Texera graph but have no model in the JointJS paper", () => {
const workflowActionService: WorkflowActionService = TestBed.inject(WorkflowActionService);
const paperHost = document.createElement("div");
document.body.appendChild(paperHost);
try {
workflowActionService.getJointGraphWrapper().attachMainJointPaper({ el: paperHost });
// findIntersectedLink walks the Texera graph but resolves each link against the
// JointJS paper, and the two can diverge. A link known only to Texera resolves to
// no joint model, so it must be skipped rather than dereferenced.
vi.spyOn(workflowActionService.getTexeraGraph(), "getAllLinks").mockReturnValue([
{
linkID: "ghost",
source: { operatorID: "op-a", portID: "op-a-output-0" },
target: { operatorID: "op-b", portID: "op-b-input-0" },
},
] as OperatorLink[]);

expect(() => (dragDropService as any).findIntersectedLink({ x: 0, y: 0 })).not.toThrow();
expect((dragDropService as any).findIntersectedLink({ x: 0, y: 0 })).toBeNull();
} finally {
document.body.removeChild(paperHost);
}
});
});

describe("handleOperatorRecommendationOnDrag (drag lifecycle)", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,10 +440,6 @@ export class DragDropService {

for (const link of allLinks) {
const jointLink = paper.getModelById(link.linkID) as joint.dia.Link;
if (!jointLink) {
continue;
}

const linkView = paper.findViewByModel(jointLink) as joint.dia.LinkView;
if (!linkView) {
continue;
Expand Down
Loading