This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/main by this push:
new c453eb0986 test(frontend): add unit test coverage for
DatasetSelectionModalComponent (#6529)
c453eb0986 is described below
commit c453eb098653bcb2f49bfc201fd40e5ec1de26d3
Author: Meng Wang <[email protected]>
AuthorDate: Sat Jul 18 19:01:32 2026 -0700
test(frontend): add unit test coverage for DatasetSelectionModalComponent
(#6529)
### What changes were proposed in this PR?
Adds a Vitest spec for `DatasetSelectionModalComponent`
(`frontend/src/app/workspace/component/dataset-selection-modal/`), which
previously had no spec (codecov ~11%).
6 tests, using `TestBed` + `detectChanges()`, with `DatasetService` and
`NzModalRef` stubbed (`vi.fn()` returning `of(...)`) and `NZ_MODAL_DATA`
provided so the modal receives its `{ fileMode, selectedPath }`:
- **create + render** — loads accessible datasets on init; the confirm
button
renders disabled until a path is chosen.
- **`ngOnInit` from `data.selectedPath`** — in file mode, splits the
path into
owner / dataset / version and initializes `selectedDataset`,
`datasetVersions`,
`selectedVersion`, and `fileTree` accordingly.
- **`onDatasetChange`** — loads the version list and (in file mode)
auto-selects
a version.
- **`onVersionChange`** — in non-file mode, composes `selectedPath` as
`/owner/dataset/version` and loads the file tree.
- **`onFileSelected`** — in file mode, sets `selectedPath` to the node's
full path.
- **`onConfirmSelection`** — closes the modal with `selectedPath`.
`DatasetService` is stubbed inline (no shared stub exists for it). No
production
code was changed.
### Any related issues, documentation, discussions?
Closes #6516
### 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/dataset-selection-modal/dataset-selection-modal.component.spec.ts
# Tests 6 passed (6)
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])
---
.../dataset-selection-modal.component.spec.ts | 164 +++++++++++++++++++++
1 file changed, 164 insertions(+)
diff --git
a/frontend/src/app/workspace/component/dataset-selection-modal/dataset-selection-modal.component.spec.ts
b/frontend/src/app/workspace/component/dataset-selection-modal/dataset-selection-modal.component.spec.ts
new file mode 100644
index 0000000000..bf3bfdb133
--- /dev/null
+++
b/frontend/src/app/workspace/component/dataset-selection-modal/dataset-selection-modal.component.spec.ts
@@ -0,0 +1,164 @@
+/**
+ * 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 { NZ_MODAL_DATA, NzModalRef } from "ng-zorro-antd/modal";
+import { DatasetSelectionModalComponent } from
"./dataset-selection-modal.component";
+import { DatasetService } from
"../../../dashboard/service/user/dataset/dataset.service";
+import { DashboardDataset } from
"../../../dashboard/type/dashboard-dataset.interface";
+import { DatasetVersion } from "../../../common/type/dataset";
+import { DatasetFileNode } from "../../../common/type/datasetVersionFileTree";
+
+const OWNER = "[email protected]";
+
+const dataset: DashboardDataset = {
+ isOwner: true,
+ ownerEmail: OWNER,
+ dataset: {
+ did: 10,
+ name: "myds",
+ ownerUid: 1,
+ isPublic: false,
+ isDownloadable: false,
+ storagePath: undefined,
+ description: "",
+ creationTime: undefined,
+ coverImage: undefined,
+ },
+ accessPrivilege: "WRITE",
+ size: 0,
+};
+
+const version: DatasetVersion = {
+ dvid: 100,
+ did: 10,
+ creatorUid: 1,
+ name: "v1",
+ versionHash: undefined,
+ creationTime: undefined,
+ fileNodes: undefined,
+};
+
+const fileNode: DatasetFileNode = { name: "a.csv", type: "file", parentDir:
`/${OWNER}/myds/v1` };
+
+describe("DatasetSelectionModalComponent", () => {
+ let component: DatasetSelectionModalComponent;
+ let fixture: ComponentFixture<DatasetSelectionModalComponent>;
+ let modalData: { fileMode: boolean; selectedPath?: string | null };
+ let modalRef: { close: ReturnType<typeof vi.fn> };
+ let datasetService: {
+ retrieveAccessibleDatasets: ReturnType<typeof vi.fn>;
+ retrieveDatasetVersionList: ReturnType<typeof vi.fn>;
+ retrieveDatasetVersionFileTree: ReturnType<typeof vi.fn>;
+ };
+
+ // Build the component after the test has configured `modalData`, so that
+ // ngOnInit (run by detectChanges) sees the intended fileMode / selectedPath.
+ function build(): void {
+ fixture = TestBed.createComponent(DatasetSelectionModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ }
+
+ beforeEach(async () => {
+ modalData = { fileMode: false };
+ modalRef = { close: vi.fn() };
+ datasetService = {
+ retrieveAccessibleDatasets: vi.fn().mockReturnValue(of([dataset])),
+ retrieveDatasetVersionList: vi.fn().mockReturnValue(of([version])),
+ retrieveDatasetVersionFileTree: vi.fn().mockReturnValue(of({ fileNodes:
[fileNode], size: 0 })),
+ };
+
+ await TestBed.configureTestingModule({
+ imports: [DatasetSelectionModalComponent],
+ providers: [
+ { provide: NZ_MODAL_DATA, useValue: modalData },
+ { provide: NzModalRef, useValue: modalRef },
+ { provide: DatasetService, useValue: datasetService },
+ ],
+ }).compileComponents();
+ });
+
+ it("creates and renders, loading the accessible datasets", () => {
+ build();
+ expect(component).toBeTruthy();
+ expect(datasetService.retrieveAccessibleDatasets).toHaveBeenCalled();
+ expect(component.datasets).toEqual([dataset]);
+ // template rendered: the confirm button is disabled until a path is
selected
+ const button: HTMLButtonElement =
fixture.nativeElement.querySelector("button[nz-button]");
+ expect(button.disabled).toBe(true);
+ });
+
+ it("ngOnInit initializes selectedDataset and selectedVersion from
data.selectedPath", () => {
+ modalData.fileMode = true;
+ modalData.selectedPath = `/${OWNER}/myds/v1`;
+
+ build();
+
+ expect(component.selectedDataset).toBe(dataset);
+ expect(component.datasetVersions).toEqual([version]);
+ expect(component.selectedVersion).toBe(version);
+ expect(component.fileTree).toEqual([fileNode]);
+ expect(datasetService.retrieveDatasetVersionList).toHaveBeenCalledWith(10);
+
expect(datasetService.retrieveDatasetVersionFileTree).toHaveBeenCalledWith(10,
100);
+ });
+
+ it("onDatasetChange loads the version list and auto-selects a version in
file mode", () => {
+ modalData.fileMode = true;
+ build();
+
+ component.selectedDataset = dataset;
+ component.onDatasetChange();
+
+ expect(datasetService.retrieveDatasetVersionList).toHaveBeenCalledWith(10);
+ expect(component.datasetVersions).toEqual([version]);
+ expect(component.selectedVersion).toBe(version);
+ });
+
+ it("onVersionChange composes selectedPath from the dataset/version in
non-file mode", () => {
+ build(); // fileMode false
+
+ component.selectedDataset = dataset;
+ component.selectedVersion = version;
+ component.onVersionChange();
+
+
expect(datasetService.retrieveDatasetVersionFileTree).toHaveBeenCalledWith(10,
100);
+ expect(component.fileTree).toEqual([fileNode]);
+ expect(component.selectedPath).toBe(`/${OWNER}/myds/v1`);
+ });
+
+ it("onFileSelected sets selectedPath to the node's full path in file mode",
() => {
+ modalData.fileMode = true;
+ build();
+
+ component.onFileSelected(fileNode);
+
+ expect(component.selectedPath).toBe(`/${OWNER}/myds/v1/a.csv`);
+ });
+
+ it("onConfirmSelection closes the modal with the selected path", () => {
+ build();
+ component.selectedPath = "/some/path";
+
+ component.onConfirmSelection();
+
+ expect(modalRef.close).toHaveBeenCalledWith("/some/path");
+ });
+});