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/07/18 23:39:39 UTC
(texera) branch gh-readonly-queue/main/pr-6509-e75562e2195ca1601262d6c92bff284cb4d71ffd created (now 8d7664d288)
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-6509-e75562e2195ca1601262d6c92bff284cb4d71ffd
in repository https://gitbox.apache.org/repos/asf/texera.git
at 8d7664d288 test(frontend): add unit test coverage for ResultExportationComponent (#6509)
This branch includes the following new commits:
new 8d7664d288 test(frontend): add unit test coverage for ResultExportationComponent (#6509)
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): add unit test coverage for ResultExportationComponent (#6509)
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-6509-e75562e2195ca1601262d6c92bff284cb4d71ffd
in repository https://gitbox.apache.org/repos/asf/texera.git
commit 8d7664d288ddb5bfd7816a1dc6eb8d2df893a7c3
Author: Meng Wang <me...@uci.edu>
AuthorDate: Sat Jul 18 16:39:17 2026 -0700
test(frontend): add unit test coverage for ResultExportationComponent (#6509)
### What changes were proposed in this PR?
Adds a behavior-focused Vitest spec for `ResultExportationComponent`
(`frontend/src/app/workspace/component/result-exportation/result-exportation.component.ts`),
which previously had no dedicated spec (codecov ~6%). It is the ng-zorro
modal
that drives result export to a dataset or a local download.
5 tests, using `TestBed` with all seven collaborators stubbed and
`NZ_MODAL_DATA` / `NzModalRef` provided (no backend, no real modal):
- **creation** — the component instantiates and `detectChanges()`
renders.
- **`ngOnInit`** — keeps only `WRITE`-accessible datasets, stores the
downloadability result, and picks up the selected computing unit.
- **`onClickExportResult("dataset", ds)`** — calls the export service
with the
dataset destination and the resolved dataset id, then closes the modal.
- **`onClickExportResult("local")`** — calls the export service with the
local
destination and no dataset ids, then closes the modal.
- **`onClickCreateNewDataset()`** — opens the dataset-creator modal
(`UserDatasetVersionCreatorComponent`) and adopts the dataset returned
on
close.
No production code was changed.
### Any related issues, documentation, discussions?
Closes #6504
### How was this PR tested?
New unit tests, run locally in `frontend/` (all green; the failure path
was
verified by breaking an assertion to confirm the suite goes red):
```
ng test --watch=false --include src/app/workspace/component/result-exportation/result-exportation.component.spec.ts
# Tests 5 passed (5)
eslint <spec> # clean
prettier --check # clean
```
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8 [1M context])
---
.../result-exportation.component.spec.ts | 168 +++++++++++++++++++++
1 file changed, 168 insertions(+)
diff --git a/frontend/src/app/workspace/component/result-exportation/result-exportation.component.spec.ts b/frontend/src/app/workspace/component/result-exportation/result-exportation.component.spec.ts
new file mode 100644
index 0000000000..866b294e56
--- /dev/null
+++ b/frontend/src/app/workspace/component/result-exportation/result-exportation.component.spec.ts
@@ -0,0 +1,168 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { of } from "rxjs";
+import { ResultExportationComponent } from "./result-exportation.component";
+import {
+ WorkflowResultDownloadability,
+ WorkflowResultExportService,
+} from "../../service/workflow-result-export/workflow-result-export.service";
+import { DatasetService } from "../../../dashboard/service/user/dataset/dataset.service";
+import { WorkflowActionService } from "../../service/workflow-graph/model/workflow-action.service";
+import { WorkflowResultService } from "../../service/workflow-result/workflow-result.service";
+import { ComputingUnitStatusService } from "../../../common/service/computing-unit/computing-unit-status/computing-unit-status.service";
+import { UserDatasetVersionCreatorComponent } from "../../../dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-version-creator/user-dataset-version-creator.component";
+import { DashboardDataset } from "../../../dashboard/type/dashboard-dataset.interface";
+import { NZ_MODAL_DATA, NzModalRef, NzModalService } from "ng-zorro-antd/modal";
+
+const writeDataset = {
+ dataset: { did: 1, name: "writable" },
+ accessPrivilege: "WRITE",
+} as unknown as DashboardDataset;
+
+const readDataset = {
+ dataset: { did: 2, name: "readonly" },
+ accessPrivilege: "READ",
+} as unknown as DashboardDataset;
+
+const MODAL_DATA = {
+ sourceTriggered: "menu",
+ workflowName: "my-workflow",
+ defaultFileName: "out.csv",
+ rowIndex: -1,
+ columnIndex: -1,
+ exportType: "csv",
+};
+
+describe("ResultExportationComponent", () => {
+ let component: ResultExportationComponent;
+ let fixture: ComponentFixture<ResultExportationComponent>;
+
+ let exportWorkflowExecutionResult: ReturnType<typeof vi.fn>;
+ let modalClose: ReturnType<typeof vi.fn>;
+ let modalCreate: ReturnType<typeof vi.fn>;
+
+ beforeEach(async () => {
+ exportWorkflowExecutionResult = vi.fn();
+ modalClose = vi.fn();
+ modalCreate = vi.fn().mockReturnValue({ afterClose: of(null) });
+
+ await TestBed.configureTestingModule({
+ imports: [ResultExportationComponent],
+ providers: [
+ { provide: NZ_MODAL_DATA, useValue: MODAL_DATA },
+ { provide: NzModalRef, useValue: { close: modalClose, getConfig: () => ({}) } },
+ { provide: NzModalService, useValue: { create: modalCreate } },
+ {
+ provide: WorkflowResultExportService,
+ useValue: {
+ computeRestrictionAnalysis: vi.fn().mockReturnValue(of(new WorkflowResultDownloadability(new Map()))),
+ exportWorkflowExecutionResult,
+ },
+ },
+ {
+ provide: DatasetService,
+ useValue: { retrieveAccessibleDatasets: vi.fn().mockReturnValue(of([writeDataset, readDataset])) },
+ },
+ {
+ provide: WorkflowActionService,
+ useValue: {
+ getTexeraGraph: vi.fn().mockReturnValue({ getAllOperators: vi.fn().mockReturnValue([]) }),
+ getJointGraphWrapper: vi
+ .fn()
+ .mockReturnValue({ getCurrentHighlightedOperatorIDs: vi.fn().mockReturnValue([]) }),
+ },
+ },
+ {
+ provide: WorkflowResultService,
+ useValue: {
+ determineOutputTypes: vi.fn().mockReturnValue({
+ hasAnyResult: false,
+ isTableOutput: false,
+ isVisualizationOutput: false,
+ containsBinaryData: false,
+ }),
+ },
+ },
+ {
+ provide: ComputingUnitStatusService,
+ useValue: { getSelectedComputingUnit: vi.fn().mockReturnValue(of(null)) },
+ },
+ ],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ResultExportationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it("should create and render", () => {
+ expect(component).toBeTruthy();
+ });
+
+ it("ngOnInit keeps only WRITE-accessible datasets and stores the downloadability", () => {
+ // detectChanges() in beforeEach already ran ngOnInit with its synchronous mock streams.
+ expect(component.userAccessibleDatasets).toEqual([writeDataset]);
+ expect(component.filteredUserAccessibleDatasets).toEqual([writeDataset]);
+ expect(component.downloadability).toBeDefined();
+ expect(component.selectedComputingUnit).toBeNull();
+ });
+
+ it("onClickExportResult('dataset', ds) exports to the dataset destination and closes the modal", () => {
+ component.onClickExportResult("dataset", writeDataset);
+
+ expect(exportWorkflowExecutionResult).toHaveBeenCalledTimes(1);
+ const args = exportWorkflowExecutionResult.mock.calls[0];
+ expect(args[0]).toBe("csv"); // exportType, from modal data
+ expect(args[1]).toBe("my-workflow"); // workflowName
+ expect(args[2]).toEqual([1]); // datasetIds resolved from ds.dataset.did
+ expect(args[6]).toBe(true); // exportAll, because sourceTriggered === "menu"
+ expect(args[7]).toBe("dataset"); // destination
+ expect(modalClose).toHaveBeenCalledTimes(1);
+ });
+
+ it("onClickExportResult('local') exports to local download with no dataset ids", () => {
+ component.onClickExportResult("local");
+
+ expect(exportWorkflowExecutionResult).toHaveBeenCalledTimes(1);
+ const args = exportWorkflowExecutionResult.mock.calls[0];
+ expect(args[2]).toEqual([]); // local download carries no dataset ids
+ expect(args[7]).toBe("local");
+ expect(modalClose).toHaveBeenCalledTimes(1);
+ });
+
+ it("onClickCreateNewDataset opens the dataset-creator modal and adopts the created dataset", () => {
+ const created = {
+ dataset: { did: 9, name: "brand-new" },
+ accessPrivilege: "WRITE",
+ } as unknown as DashboardDataset;
+ modalCreate.mockReturnValue({ afterClose: of(created) });
+
+ component.onClickCreateNewDataset();
+
+ expect(modalCreate).toHaveBeenCalledTimes(1);
+ const config = modalCreate.mock.calls[0][0];
+ expect(config.nzTitle).toBe("Create New Dataset");
+ expect(config.nzContent).toBe(UserDatasetVersionCreatorComponent);
+ // afterClose emitted a dataset, so the component adopts it into its lists.
+ expect(component.userAccessibleDatasets[0]).toBe(created);
+ expect(component.inputDatasetName).toBe("brand-new");
+ });
+});