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);
+ });
+ });
+ });
+});