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 964e915baa test(frontend): add unit tests for AdminUserService (#6467)
964e915baa is described below

commit 964e915baae29601b8a81d0e90fe2ca7da35ceca
Author: Matthew B. <[email protected]>
AuthorDate: Tue Jul 21 19:44:32 2026 -0700

    test(frontend): add unit tests for AdminUserService (#6467)
    
    ### What changes were proposed in this PR?
    - Adds admin-user.service.spec.ts covering AdminUserService; no
    production code changed.
    - Verifies the user list/update/add endpoints and the per-user quota GET
    endpoints.
    - Asserts which endpoints send the user_id query param and which do not.
    ### Any related issues, documentation, discussions?
    Closes: #6455
    ### How was this PR tested?
    - Run `cd frontend && npx nx test gui
    --include="**/admin-user.service.spec.ts"`, expect 11 passed.
    - Full frontend suite runs in CI via `yarn test:ci`, selected by the
    auto-applied `frontend` label.
    ### Was this PR authored or co-authored using generative AI tooling?
    Co-authored with Claude Opus 4.8 in compliance with ASF
---
 .../service/admin/user/admin-user.service.spec.ts  | 187 +++++++++++++++++++++
 1 file changed, 187 insertions(+)

diff --git 
a/frontend/src/app/dashboard/service/admin/user/admin-user.service.spec.ts 
b/frontend/src/app/dashboard/service/admin/user/admin-user.service.spec.ts
new file mode 100644
index 0000000000..19a8aa7976
--- /dev/null
+++ b/frontend/src/app/dashboard/service/admin/user/admin-user.service.spec.ts
@@ -0,0 +1,187 @@
+/**
+ * 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 { HttpClientTestingModule, HttpTestingController } from 
"@angular/common/http/testing";
+import { TestBed } from "@angular/core/testing";
+import {
+  AdminUserService,
+  USER_LIST_URL,
+  USER_UPDATE_URL,
+  USER_ADD_URL,
+  USER_CREATED_FILES,
+  USER_CREATED_DATASETS,
+  USER_CREATED_WORKFLOWS,
+  USER_ACCESS_FILES,
+  USER_ACCESS_WORKFLOWS,
+  USER_QUOTA_SIZE,
+  USER_DELETE_EXECUTION_COLLECTION,
+} from "./admin-user.service";
+import { Role } from "../../../../common/type/user";
+import { Observable } from "rxjs";
+
+describe("AdminUserService", () => {
+  let service: AdminUserService;
+  let httpMock: HttpTestingController;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      imports: [HttpClientTestingModule],
+      providers: [AdminUserService],
+    });
+    service = TestBed.inject(AdminUserService);
+    httpMock = TestBed.inject(HttpTestingController);
+  });
+
+  afterEach(() => {
+    httpMock.verify();
+  });
+
+  it("should be created", () => {
+    expect(service).toBeTruthy();
+  });
+
+  it("getUserList() GETs the list endpoint", () => {
+    const users = [{ uid: 1 } as any];
+    let result: readonly any[] | undefined;
+    service.getUserList().subscribe(r => (result = r));
+
+    const req = httpMock.expectOne(USER_LIST_URL);
+    expect(req.request.method).toEqual("GET");
+    req.flush(users);
+
+    expect(result).toEqual(users);
+  });
+
+  it("updateUser() PUTs the full user record", () => {
+    service.updateUser(1, "Alice", "[email protected]", Role.ADMIN, 
"vip").subscribe();
+
+    const req = httpMock.expectOne(USER_UPDATE_URL);
+    expect(req.request.method).toEqual("PUT");
+    expect(req.request.body).toEqual({
+      uid: 1,
+      name: "Alice",
+      email: "[email protected]",
+      role: Role.ADMIN,
+      comment: "vip",
+    });
+    req.flush(null);
+  });
+
+  it("addUser() POSTs an empty body to the trailing-slash add endpoint", () => 
{
+    service.addUser().subscribe();
+
+    const req = httpMock.expectOne(`${USER_ADD_URL}/`);
+    expect(req.request.method).toEqual("POST");
+    expect(req.request.body).toEqual({});
+    req.flush({});
+  });
+
+  it("getUploadedFiles() sends the uid as a user_id query param", () => {
+    service.getUploadedFiles(9).subscribe();
+
+    const req = httpMock.expectOne(r => r.url === USER_CREATED_FILES);
+    expect(req.request.params.get("user_id")).toEqual("9");
+    req.flush([]);
+  });
+
+  it("getCreatedDatasets() GETs without a query param", () => {
+    service.getCreatedDatasets(9).subscribe();
+
+    const req = httpMock.expectOne(USER_CREATED_DATASETS);
+    expect(req.request.method).toEqual("GET");
+    expect(req.request.params.keys().length).toEqual(0);
+    req.flush([]);
+  });
+
+  it("getCreatedWorkflows() sends the uid as a user_id query param", () => {
+    service.getCreatedWorkflows(3).subscribe();
+
+    const req = httpMock.expectOne(r => r.url === USER_CREATED_WORKFLOWS);
+    expect(req.request.params.get("user_id")).toEqual("3");
+    req.flush([]);
+  });
+
+  it("getAccessFiles() sends the uid as a user_id query param", () => {
+    service.getAccessFiles(3).subscribe();
+
+    const req = httpMock.expectOne(r => r.url === USER_ACCESS_FILES);
+    expect(req.request.params.get("user_id")).toEqual("3");
+    req.flush([]);
+  });
+
+  it("getAccessWorkflows() sends the uid as a user_id query param", () => {
+    service.getAccessWorkflows(3).subscribe();
+
+    const req = httpMock.expectOne(r => r.url === USER_ACCESS_WORKFLOWS);
+    expect(req.request.params.get("user_id")).toEqual("3");
+    req.flush([]);
+  });
+
+  it("getExecutionQuota() sends the uid as a user_id query param", () => {
+    service.getExecutionQuota(3).subscribe();
+
+    const req = httpMock.expectOne(r => r.url === USER_QUOTA_SIZE);
+    expect(req.request.params.get("user_id")).toEqual("3");
+    req.flush([]);
+  });
+
+  it("deleteExecutionCollection() DELETEs the per-execution endpoint", () => {
+    service.deleteExecutionCollection(77).subscribe();
+
+    const req = httpMock.expectOne(`${USER_DELETE_EXECUTION_COLLECTION}/77`);
+    expect(req.request.method).toEqual("DELETE");
+    req.flush(null);
+  });
+
+  describe("error propagation", () => {
+    const cases: { name: string; call: () => Observable<unknown>; url: string 
}[] = [
+      { name: "getUserList", call: () => service.getUserList(), url: 
USER_LIST_URL },
+      {
+        name: "updateUser",
+        call: () => service.updateUser(1, "Alice", "[email protected]", Role.ADMIN, 
"vip"),
+        url: USER_UPDATE_URL,
+      },
+      { name: "addUser", call: () => service.addUser(), url: 
`${USER_ADD_URL}/` },
+      { name: "getUploadedFiles", call: () => service.getUploadedFiles(9), 
url: USER_CREATED_FILES },
+      { name: "getCreatedDatasets", call: () => service.getCreatedDatasets(9), 
url: USER_CREATED_DATASETS },
+      { name: "getCreatedWorkflows", call: () => 
service.getCreatedWorkflows(3), url: USER_CREATED_WORKFLOWS },
+      { name: "getAccessFiles", call: () => service.getAccessFiles(3), url: 
USER_ACCESS_FILES },
+      { name: "getAccessWorkflows", call: () => service.getAccessWorkflows(3), 
url: USER_ACCESS_WORKFLOWS },
+      { name: "getExecutionQuota", call: () => service.getExecutionQuota(3), 
url: USER_QUOTA_SIZE },
+      {
+        name: "deleteExecutionCollection",
+        call: () => service.deleteExecutionCollection(7),
+        url: `${USER_DELETE_EXECUTION_COLLECTION}/7`,
+      },
+    ];
+
+    cases.forEach(({ name, call, url }) => {
+      it(`${name}() propagates HTTP errors to the subscriber`, () => {
+        const onError = vi.fn();
+        call().subscribe({ error: onError });
+
+        const req = httpMock.expectOne(r => r.url === url);
+        req.flush("boom", { status: 500, statusText: "Server Error" });
+
+        expect(onError).toHaveBeenCalledTimes(1);
+        expect(onError.mock.calls[0][0].status).toEqual(500);
+      });
+    });
+  });
+});

Reply via email to