Copilot commented on code in PR #7682:
URL: https://github.com/apache/texera/pull/7682#discussion_r3788405554


##########
frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.spec.ts:
##########
@@ -2050,5 +2109,99 @@ describe("DatasetDetailComponent behavior", () => {
       switches[1].triggerEventHandler("ngModelChange", false);
       
expect(datasetServiceStub.updateDatasetDownloadable).toHaveBeenCalledWith(5);
     });
+
+    // ─── contributor management ─────────────────────────────────────────────
+    const contributors = [
+      { name: "Ada", email: "[email protected]", affiliation: "" } as Contributor,
+      { name: "Grace", email: "[email protected]", affiliation: "" } as Contributor,
+    ];
+
+    it("renders a row per contributor with the actions trigger", () => {
+      renderWith({ did: 5, datasetContributors: [...contributors], 
userDatasetAccessLevel: "WRITE" });
+
+      const rendered = fixture.nativeElement.textContent ?? "";
+      expect(rendered).toContain("Ada");
+      expect(rendered).toContain("Grace");
+      // each row carries the dropdown trigger that hosts Edit/Delete
+      const triggers = fixture.debugElement
+        .queryAll(By.css("button[nz-dropdown]"))
+        .filter(btn => btn.nativeElement.querySelector("i.anticon-more"));
+      expect(triggers.length).toBe(contributors.length);
+    });
+
+    // Edit/Delete live inside an nz-dropdown-menu, which only mounts into a 
CDK overlay on a
+    // real user open — jsdom does not drive that. Assert the handlers those 
menu items bind to
+    // instead; the rendered trigger is covered above.
+    it("edits the chosen contributor through the menu's binding target", () => 
{
+      const updated = { ...contributors[0], affiliation: "Lab" };
+      modalServiceStub.create.mockReturnValue({ afterClose: of(updated) });
+      renderWith({ did: 5, datasetContributors: [...contributors], 
userDatasetAccessLevel: "WRITE" });
+
+      component.onEditContributor(contributors[0]);
+
+      expect(component.datasetContributors[0]).toEqual(updated);
+    });
+
+    it("deletes the chosen contributor through the popconfirm's binding 
target", () => {
+      renderWith({ did: 5, datasetContributors: [...contributors], 
userDatasetAccessLevel: "WRITE" });
+
+      component.onDeleteContributor(contributors[0]);
+
+      expect(component.datasetContributors.map(c => 
c.name)).toEqual(["Grace"]);
+    });
+
+    // ─── view controls ──────────────────────────────────────────────────────
+
+    it("downloads the current file from the toolbar", () => {
+      // the toolbar controls are behind *ngIf="selectedVersion"
+      renderWith({ did: 5, selectedVersion: { dvid: 1, name: "v1" } as 
DatasetVersion });
+      openTab("Versions & Files");
+      const onDownload = vi.spyOn(component, 
"onClickDownloadCurrentFile").mockImplementation(() => {});
+
+      const downloadBtn = fixture.debugElement
+        .queryAll(By.css("button"))
+        .find(btn => btn.nativeElement.querySelector("i.anticon-download"));
+      expect(downloadBtn).toBeTruthy();
+      downloadBtn!.triggerEventHandler("click", null);
+
+      expect(onDownload).toHaveBeenCalled();
+    });
+
+    it("toggles the scaled view from the toolbar", () => {
+      renderWith({ did: 5, isMaximized: false, selectedVersion: { dvid: 1, 
name: "v1" } as DatasetVersion });
+      openTab("Versions & Files");
+
+      const scaleBtn = fixture.debugElement
+        .queryAll(By.css("button"))
+        .find(btn => btn.nativeElement.querySelector("i.anticon-expand, 
i.anticon-compress"));
+      expect(scaleBtn).toBeTruthy();
+      scaleBtn!.triggerEventHandler("click", null);
+      fixture.detectChanges();
+
+      expect(component.isMaximized).toBe(true);
+    });
+
+    // ─── sider resize ───────────────────────────────────────────────────────
+
+    it("applies the dragged sider width on the next animation frame", async () 
=> {
+      renderWith({ did: 5 });
+
+      component.onSideResize({ width: 321 } as NzResizeEvent);
+      // the handler defers to requestAnimationFrame; let that frame run
+      await new Promise(resolve => requestAnimationFrame(() => resolve(null)));
+
+      expect(component.siderWidth).toBe(321);
+    });
+
+    it("cancels a pending resize frame before scheduling the next one", () => {
+      renderWith({ did: 5 });
+      const cancel = vi.spyOn(globalThis, "cancelAnimationFrame");
+
+      component.onSideResize({ width: 100 } as NzResizeEvent);
+      component.onSideResize({ width: 200 } as NzResizeEvent);
+
+      expect(cancel).toHaveBeenCalled();
+      cancel.mockRestore();
+    });

Review Comment:
   This test asserts `cancelAnimationFrame` was called, but the first 
`onSideResize` call already invokes `cancelAnimationFrame(this.id)` with the 
initial `id = -1`. That means the assertion can pass even if a previously 
scheduled frame is never canceled. Consider also spying on 
`requestAnimationFrame` to return a known id, clear the cancel spy after the 
first call, and then assert the second call cancels the first id (e.g., 
`toHaveBeenCalledWith(100)`).



-- 
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]

Reply via email to