mengw15 commented on code in PR #7336:
URL: https://github.com/apache/texera/pull/7336#discussion_r3720346030
##########
frontend/src/app/dashboard/component/user/list-item/card-item/card-item.component.spec.ts:
##########
@@ -894,4 +895,153 @@ describe("CardItemComponent", () => {
expect(component.likeCount).toBe(0);
});
});
+
+ describe("template rendering", () => {
+ const stop = { stopPropagation: () => {} };
+
+ it("renders the full private-search action set for an owned workflow (and
no like button)", () => {
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ component.currentUid = 1;
+ fixture.detectChanges();
+
+ const de = fixture.debugElement;
+ expect(de.query(By.css(".card-checkbox"))).toBeTruthy();
+ expect(de.query(By.css(".edit-btn"))).toBeTruthy();
+ expect(de.query(By.css('button[title="Detail"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Share"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Copy"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Download"]'))).toBeTruthy();
+ expect(de.query(By.css(".delete-btn"))).toBeTruthy();
+ // the like button is only rendered in non-private mode
+ expect(de.query(By.css(".like-btn"))).toBeNull();
+ });
+
+ it("wires each private-search action click to its handler / output", () =>
{
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ component.currentUid = 1;
+ fixture.detectChanges();
+ const de = fixture.debugElement;
+
+ const detailSpy = vi.spyOn(component,
"openDetailModal").mockImplementation(() => {});
+ const shareSpy = vi.spyOn(component,
"onClickOpenShareAccess").mockImplementation(async () => {});
+ const downloadSpy = vi.spyOn(component,
"onClickDownload").mockImplementation(async () => {});
+ let duplicated = false;
+ component.duplicated.subscribe(() => (duplicated = true));
+ let deleted = false;
+ component.deleted.subscribe(() => (deleted = true));
+
+ de.query(By.css('button[title="Detail"]')).triggerEventHandler("click",
stop);
+ de.query(By.css('button[title="Share"]')).triggerEventHandler("click",
stop);
+
de.query(By.css('button[title="Download"]')).triggerEventHandler("click", stop);
+ de.query(By.css('button[title="Copy"]')).triggerEventHandler("click",
stop);
+ de.query(By.css(".delete-btn")).triggerEventHandler("nzOnConfirm",
undefined);
+
+ expect(detailSpy).toHaveBeenCalled();
+ expect(shareSpy).toHaveBeenCalled();
+ expect(downloadSpy).toHaveBeenCalled();
+ expect(duplicated).toBe(true);
+ expect(deleted).toBe(true);
+ });
+
+ it("enters name-editing mode from the edit button and swaps the display
for the input", () => {
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ fixture.detectChanges();
+
+ // Trigger via the DOM; onEditName sets editingName synchronously (its
setTimeout
+ // focus callback never runs in this synchronous test — no fake timers
needed).
+
fixture.debugElement.query(By.css(".edit-btn")).triggerEventHandler("click",
stop);
+ expect(component.editingName).toBe(true);
+
+ fixture.detectChanges();
+
expect(fixture.debugElement.query(By.css(".resource-name-edit-input"))).toBeTruthy();
+ expect(fixture.debugElement.query(By.css(".resource-name"))).toBeNull();
+
+ // pressing Enter in the edit input confirms the rename (real key event
so the
+ // Angular keydown.enter binding fires through its event plugin)
+ const confirmSpy = vi.spyOn(component,
"confirmUpdateCustomName").mockImplementation(() => {});
+ const editInput =
fixture.debugElement.query(By.css(".resource-name-edit-input"))
+ .nativeElement as HTMLInputElement;
+ editInput.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter" }));
+ expect(confirmSpy).toHaveBeenCalled();
+ });
+
+ it("renders and wires the cover-image controls when the cover is
editable", () => {
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ // hasCustomImage is driven by the private customImage field.
+ (component as unknown as { customImage?: string }).customImage =
"http://example.com/cover.png";
Review Comment:
Switched to driving `hasCustomImage` through the public entry input
(`coverImageUrl` → `initializeEntry()`), so the test no longer casts to the
private `customImage` field.
##########
frontend/src/app/dashboard/component/user/list-item/card-item/card-item.component.spec.ts:
##########
@@ -894,4 +895,153 @@ describe("CardItemComponent", () => {
expect(component.likeCount).toBe(0);
});
});
+
+ describe("template rendering", () => {
+ const stop = { stopPropagation: () => {} };
+
+ it("renders the full private-search action set for an owned workflow (and
no like button)", () => {
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ component.currentUid = 1;
+ fixture.detectChanges();
+
+ const de = fixture.debugElement;
+ expect(de.query(By.css(".card-checkbox"))).toBeTruthy();
+ expect(de.query(By.css(".edit-btn"))).toBeTruthy();
+ expect(de.query(By.css('button[title="Detail"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Share"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Copy"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Download"]'))).toBeTruthy();
+ expect(de.query(By.css(".delete-btn"))).toBeTruthy();
+ // the like button is only rendered in non-private mode
+ expect(de.query(By.css(".like-btn"))).toBeNull();
+ });
+
+ it("wires each private-search action click to its handler / output", () =>
{
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ component.currentUid = 1;
+ fixture.detectChanges();
+ const de = fixture.debugElement;
+
+ const detailSpy = vi.spyOn(component,
"openDetailModal").mockImplementation(() => {});
+ const shareSpy = vi.spyOn(component,
"onClickOpenShareAccess").mockImplementation(async () => {});
+ const downloadSpy = vi.spyOn(component,
"onClickDownload").mockImplementation(async () => {});
+ let duplicated = false;
+ component.duplicated.subscribe(() => (duplicated = true));
+ let deleted = false;
+ component.deleted.subscribe(() => (deleted = true));
+
+ de.query(By.css('button[title="Detail"]')).triggerEventHandler("click",
stop);
+ de.query(By.css('button[title="Share"]')).triggerEventHandler("click",
stop);
+
de.query(By.css('button[title="Download"]')).triggerEventHandler("click", stop);
+ de.query(By.css('button[title="Copy"]')).triggerEventHandler("click",
stop);
+ de.query(By.css(".delete-btn")).triggerEventHandler("nzOnConfirm",
undefined);
Review Comment:
Added a `fire()` helper that queries, asserts the element is present, then
dispatches the event — so a broken selector fails with a clear message instead
of a null dereference.
##########
frontend/src/app/dashboard/component/user/list-item/card-item/card-item.component.spec.ts:
##########
@@ -894,4 +895,153 @@ describe("CardItemComponent", () => {
expect(component.likeCount).toBe(0);
});
});
+
+ describe("template rendering", () => {
+ const stop = { stopPropagation: () => {} };
+
+ it("renders the full private-search action set for an owned workflow (and
no like button)", () => {
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ component.currentUid = 1;
+ fixture.detectChanges();
+
+ const de = fixture.debugElement;
+ expect(de.query(By.css(".card-checkbox"))).toBeTruthy();
+ expect(de.query(By.css(".edit-btn"))).toBeTruthy();
+ expect(de.query(By.css('button[title="Detail"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Share"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Copy"]'))).toBeTruthy();
+ expect(de.query(By.css('button[title="Download"]'))).toBeTruthy();
+ expect(de.query(By.css(".delete-btn"))).toBeTruthy();
+ // the like button is only rendered in non-private mode
+ expect(de.query(By.css(".like-btn"))).toBeNull();
+ });
+
+ it("wires each private-search action click to its handler / output", () =>
{
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ component.currentUid = 1;
+ fixture.detectChanges();
+ const de = fixture.debugElement;
+
+ const detailSpy = vi.spyOn(component,
"openDetailModal").mockImplementation(() => {});
+ const shareSpy = vi.spyOn(component,
"onClickOpenShareAccess").mockImplementation(async () => {});
+ const downloadSpy = vi.spyOn(component,
"onClickDownload").mockImplementation(async () => {});
+ let duplicated = false;
+ component.duplicated.subscribe(() => (duplicated = true));
+ let deleted = false;
+ component.deleted.subscribe(() => (deleted = true));
+
+ de.query(By.css('button[title="Detail"]')).triggerEventHandler("click",
stop);
+ de.query(By.css('button[title="Share"]')).triggerEventHandler("click",
stop);
+
de.query(By.css('button[title="Download"]')).triggerEventHandler("click", stop);
+ de.query(By.css('button[title="Copy"]')).triggerEventHandler("click",
stop);
+ de.query(By.css(".delete-btn")).triggerEventHandler("nzOnConfirm",
undefined);
+
+ expect(detailSpy).toHaveBeenCalled();
+ expect(shareSpy).toHaveBeenCalled();
+ expect(downloadSpy).toHaveBeenCalled();
+ expect(duplicated).toBe(true);
+ expect(deleted).toBe(true);
+ });
+
+ it("enters name-editing mode from the edit button and swaps the display
for the input", () => {
+ component.entry = makeWorkflowEntry();
+ component.isPrivateSearch = true;
+ fixture.detectChanges();
+
+ // Trigger via the DOM; onEditName sets editingName synchronously (its
setTimeout
+ // focus callback never runs in this synchronous test — no fake timers
needed).
+
fixture.debugElement.query(By.css(".edit-btn")).triggerEventHandler("click",
stop);
Review Comment:
Intentionally not using fake timers here: issue #7330 calls this out
explicitly — layering `vi.useFakeTimers()` over zone.js's patched timers is
Node-version-dependent and has caused CI-only failures in this repo. The test
body is synchronous, so `onEditName`'s `setTimeout` focus callback never runs;
the test asserts `editingName` / the rendered input rather than the focus.
##########
frontend/src/app/dashboard/component/user/list-item/card-item/card-item.component.spec.ts:
##########
@@ -894,4 +895,153 @@ describe("CardItemComponent", () => {
expect(component.likeCount).toBe(0);
});
});
+
+ describe("template rendering", () => {
+ const stop = { stopPropagation: () => {} };
Review Comment:
Clicks now dispatch a real `MouseEvent`, so handlers calling
`stopPropagation()` / `preventDefault()` work.
--
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]