You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/08/07 01:37:47 UTC
(texera) branch gh-readonly-queue/main/pr-7370-e4205c357a2271b89892eadb72f3efbc7012c37c created (now 2cd542f613)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-7370-e4205c357a2271b89892eadb72f3efbc7012c37c
in repository https://gitbox.apache.org/repos/asf/texera.git
at 2cd542f613 test(frontend): extend UserWorkflowComponent template coverage (#7370)
This branch includes the following new commits:
new 2cd542f613 test(frontend): extend UserWorkflowComponent template coverage (#7370)
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(texera) 01/01: test(frontend): extend UserWorkflowComponent template coverage (#7370)
Posted by gi...@apache.org.
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-7370-e4205c357a2271b89892eadb72f3efbc7012c37c
in repository https://gitbox.apache.org/repos/asf/texera.git
commit 2cd542f613df3a07fccff0fbe97a9a9c012ed2a2
Author: Meng Wang <me...@uci.edu>
AuthorDate: Thu Aug 6 18:37:36 2026 -0700
test(frontend): extend UserWorkflowComponent template coverage (#7370)
### What changes were proposed in this PR?
Extends `user-workflow.component.spec.ts` to render the template
branches the
existing class-focused tests never reached, taking
`user-workflow.component.html`
from ~53% to 100% (104/104; the class was already at 221/221). 11 new
tests under
a `template rendering` block:
- **toolbar** — the Create button, the sort-button's `sortMethodChange`,
and the
view-type List/Card toggle.
- **multi-select actions** (rendered only once an entry is checked) —
Batch
Select, Download-as-ZIP, Duplicate, and the Delete popconfirm.
- **project actions** — the add/remove-from-project buttons that appear
when a
`pid` is set.
- **outputs** — the rendered `texera-search-results` outputs (deleted /
duplicated
/ refresh / notifyWorkflow) and the `#workflowCardTpl` card in card view
with
its card-item outputs (deleted / duplicated / refresh /
checkboxChanged).
Interactions go through the DOM (`By.css` + `triggerEventHandler`); the
backing
services are the existing stubs. No production code was changed.
### Any related issues, documentation, discussions?
Closes #7362.
### How was this PR tested?
`ng test --watch=false --include
src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts`
— 69 passed (58 existing + 11 new), run 3x for determinism. Coverage
(`--coverage`)
confirms `user-workflow.component.html` at 104/104 and the class at
221/221. The
failure path was verified by breaking an assertion (red, non-zero exit);
eslint and
prettier are clean.
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8 [1M context])
---------
Signed-off-by: Xinyuan Lin <xi...@uci.edu>
Co-authored-by: Xinyuan Lin <xi...@uci.edu>
Co-authored-by: Copilot Autofix powered by AI <17...@users.noreply.github.com>
---
.../user-workflow/user-workflow.component.spec.ts | 144 +++++++++++++++++++++
1 file changed, 144 insertions(+)
diff --git a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts
index fa5c2b3dce..7b71ead98c 100644
--- a/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts
+++ b/frontend/src/app/dashboard/component/user/user-workflow/user-workflow.component.spec.ts
@@ -18,6 +18,7 @@
*/
import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { By } from "@angular/platform-browser";
import { RouterTestingModule } from "@angular/router/testing";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
@@ -1019,5 +1020,148 @@ describe("SavedWorkflowSectionComponent", () => {
});
});
});
+
+ describe("template rendering", () => {
+ const VIEW_MODE_KEY = "texera.userWorkflow.viewMode";
+ const q = (selector: string) => fixture.debugElement.query(By.css(selector));
+
+ afterEach(() => {
+ vi.restoreAllMocks();
+ localStorage.removeItem(VIEW_MODE_KEY);
+ });
+ // The multi-select toolbar only renders when at least one entry is checked.
+ // Clone a real fixture entry (preserving its prototype) so the rendered
+ // search-results can display it, and flip `checked` on the copy so the shared
+ // fixture is not mutated.
+ const renderWithSelection = () => {
+ const source = testWorkflowEntries[0];
+ const checkedEntry = Object.assign(Object.create(Object.getPrototypeOf(source)), source);
+ checkedEntry.checked = true;
+ component.searchResultsComponent.entries = [checkedEntry];
+ fixture.detectChanges();
+ };
+
+ it("hides the multi-select actions until an entry is checked", () => {
+ component.searchResultsComponent.entries = [];
+ fixture.detectChanges();
+ expect(q('[title="Batch Select"]')).toBeNull();
+
+ renderWithSelection();
+ expect(q('[title="Batch Select"]')).toBeTruthy();
+ });
+
+ it("wires the Create Workflow button", () => {
+ const spy = vi.spyOn(component, "onClickCreateNewWorkflowFromDashboard").mockImplementation(() => {});
+ q(".create-btn").triggerEventHandler("click", null);
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it("re-searches when the sort button changes the sort method", () => {
+ const searchSpy = vi.spyOn(component, "search").mockResolvedValue(undefined);
+ q("texera-sort-button").triggerEventHandler("sortMethodChange", "NameAsc");
+ expect(component.sortMethod).toBe("NameAsc");
+ expect(searchSpy).toHaveBeenCalled();
+ });
+
+ it("wires the Batch Select button", () => {
+ renderWithSelection();
+ const spy = vi.spyOn(component, "toggleSelection").mockImplementation(() => {});
+ q('[title="Batch Select"]').triggerEventHandler("click", null);
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it("wires the Download-as-ZIP button", () => {
+ renderWithSelection();
+ const spy = vi.spyOn(component, "onClickOpenDownloadZip").mockResolvedValue(undefined);
+ q('[title="Download added workflow as a ZIP file"]').triggerEventHandler("click", null);
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it("wires the Duplicate-selected button", () => {
+ renderWithSelection();
+ const spy = vi.spyOn(component, "onClickDuplicateSelectedWorkflows").mockImplementation(() => {});
+ q('[nz-tooltip="Duplicate selected workflows"]').triggerEventHandler("click", null);
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it("wires the Delete-selected popconfirm", () => {
+ renderWithSelection();
+ const spy = vi.spyOn(component, "handleConfirmDeleteSelectedWorkflows").mockImplementation(() => {});
+ q('[nzPopconfirmTitle="Confirm to delete selected workflows."]').triggerEventHandler("nzOnConfirm", null);
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it("shows and wires the project add/remove buttons when a pid is set", () => {
+ component.pid = 1;
+ fixture.detectChanges();
+ const addSpy = vi.spyOn(component, "onClickOpenAddWorkflow").mockImplementation(() => {});
+ const removeSpy = vi.spyOn(component, "onClickOpenRemoveWorkflow").mockImplementation(() => {});
+
+ q('[title="Add workflow(s) to project"]').triggerEventHandler("click", null);
+ q('[title="Remove workflow(s) from project"]').triggerEventHandler("click", null);
+
+ expect(addSpy).toHaveBeenCalled();
+ expect(removeSpy).toHaveBeenCalled();
+ });
+
+ it("switches the view type through the List/Card buttons", () => {
+ component.viewType = "card";
+ fixture.detectChanges();
+
+ q('[title="List View"]').triggerEventHandler("click", null);
+ expect(component.viewType).toBe("list");
+
+ fixture.detectChanges();
+ q('[title="Card View"]').triggerEventHandler("click", null);
+ expect(component.viewType).toBe("card");
+ });
+
+ it("wires the rendered search-results outputs to the component", () => {
+ const results = fixture.debugElement.query(By.directive(SearchResultsComponent));
+ const deleteSpy = vi.spyOn(component, "deleteWorkflow").mockImplementation(() => {});
+ const duplicateSpy = vi.spyOn(component, "onClickDuplicateWorkflow").mockResolvedValue(undefined);
+ const refreshSpy = vi.spyOn(component, "refreshSearchResult").mockImplementation(() => {});
+ const tooltipSpy = vi.spyOn(component, "updateTooltip").mockImplementation(() => {});
+ const entry = testWorkflowEntries[0];
+
+ results.triggerEventHandler("deleted", entry);
+ results.triggerEventHandler("duplicated", entry);
+ results.triggerEventHandler("refresh", undefined);
+ results.triggerEventHandler("notifyWorkflow", undefined);
+
+ expect(deleteSpy).toHaveBeenCalledWith(entry);
+ expect(duplicateSpy).toHaveBeenCalledWith(entry);
+ expect(refreshSpy).toHaveBeenCalled();
+ expect(tooltipSpy).toHaveBeenCalled();
+ });
+
+ it("renders the workflow card template in card view and wires its outputs", () => {
+ const source = testWorkflowEntries[0];
+ const entry = Object.assign(Object.create(Object.getPrototypeOf(source)), source);
+ component.viewType = "card";
+ component.searchResultsComponent.entries = [entry];
+ fixture.detectChanges();
+
+ const card = fixture.debugElement.query(By.css("texera-card-item"));
+ expect(card).toBeTruthy();
+
+ const deleteSpy = vi.spyOn(component, "deleteWorkflow").mockImplementation(() => {});
+ const duplicateSpy = vi.spyOn(component, "onClickDuplicateWorkflow").mockResolvedValue(undefined);
+ const refreshSpy = vi.spyOn(component, "refreshSearchResult").mockImplementation(() => {});
+ const checkboxSpy = vi
+ .spyOn(component.searchResultsComponent, "onEntryCheckboxChange")
+ .mockImplementation(() => {});
+
+ card.triggerEventHandler("deleted", undefined);
+ card.triggerEventHandler("duplicated", undefined);
+ card.triggerEventHandler("refresh", undefined);
+ card.triggerEventHandler("checkboxChanged", undefined);
+
+ expect(deleteSpy).toHaveBeenCalledWith(entry);
+ expect(duplicateSpy).toHaveBeenCalledWith(entry);
+ expect(refreshSpy).toHaveBeenCalled();
+ expect(checkboxSpy).toHaveBeenCalled();
+ });
+ });
});
});