mengw15 commented on code in PR #6526:
URL: https://github.com/apache/texera/pull/6526#discussion_r3609429595
##########
frontend/src/app/dashboard/component/admin/user/admin-user.component.spec.ts:
##########
@@ -157,4 +203,174 @@ describe("AdminUserComponent", () => {
expect(component.nameSearchValue).toBe("");
expect(component.emailSearchValue).toBe("");
});
+
+ it("addUser creates a user through the service and reloads the list", () => {
+ const listCallsBefore = adminUserServiceSpy.getUserList.mock.calls.length;
+
+ component.addUser();
+
+ expect(adminUserServiceSpy.addUser).toHaveBeenCalledTimes(1);
+ // the subscribe callback re-runs ngOnInit, which re-fetches the user list
+
expect(adminUserServiceSpy.getUserList.mock.calls.length).toBe(listCallsBefore
+ 1);
+ });
+
+ it("startEdit loads the target row's values into the edit fields", () => {
+ component.startEdit(userB, "email");
+
+ expect(component.editUid).toBe(userB.uid);
+ expect(component.editAttribute).toBe("email");
+ expect(component.editName).toBe(userB.name);
+ expect(component.editEmail).toBe(userB.email);
+ expect(component.editRole).toBe(userB.role);
+ expect(component.editComment).toBe(userB.comment);
+ });
+
+ it("saveEdit persists a changed row and updates the local lists", () => {
+ component.userList = [userA];
+ component.listOfDisplayUser = [userA];
+ component.editUid = userA.uid;
+ component.editName = "Alice Updated";
+ component.editEmail = userA.email;
+ component.editRole = userA.role;
+ component.editComment = userA.comment;
+
+ component.saveEdit();
+
+ expect(adminUserServiceSpy.updateUser).toHaveBeenCalledWith(
+ userA.uid,
+ "Alice Updated",
+ userA.email,
+ userA.role,
+ userA.comment
+ );
+ expect(component.userList.find(u => u.uid ===
userA.uid)?.name).toBe("Alice Updated");
+ expect(component.listOfDisplayUser.find(u => u.uid ===
userA.uid)?.name).toBe("Alice Updated");
+ expect(component.editUid).toBe(0); // stopEdit ran
+ });
+
+ it("saveEdit is a no-op when nothing changed", () => {
+ component.userList = [userA];
+ component.editUid = userA.uid;
+ component.editName = userA.name;
+ component.editEmail = userA.email;
+ component.editRole = userA.role;
+ component.editComment = userA.comment;
+
+ component.saveEdit();
+
+ expect(adminUserServiceSpy.updateUser).not.toHaveBeenCalled();
+ expect(component.editUid).toBe(0);
+ });
+
+ it("saveEdit surfaces a service error through the message service", () => {
+ const errorSpy = vi.spyOn(TestBed.inject(NzMessageService),
"error").mockReturnValue({} as any);
+ adminUserServiceSpy.updateUser.mockReturnValue(throwError(() => ({ error:
{ message: "update failed" } })));
+
+ component.userList = [userA];
+ component.editUid = userA.uid;
+ component.editName = "Changed";
+ component.editEmail = userA.email;
+ component.editRole = userA.role;
+ component.editComment = userA.comment;
+
+ component.saveEdit();
+
+ expect(errorSpy).toHaveBeenCalledWith("update failed");
+ });
+
+ it("stopEdit clears the edit target", () => {
+ component.editUid = 5;
+ component.editAttribute = "name";
+
+ component.stopEdit();
+
+ expect(component.editUid).toBe(0);
+ expect(component.editAttribute).toBe("");
+ });
+
+ it("reset clears search state and restores the full display list", () => {
+ component.userList = [userA, userB];
+ component.nameSearchValue = "Alice";
+ component.emailSearchValue = "[email protected]";
+ component.commentSearchValue = "c";
+ component.nameSearchVisible = true;
+ component.emailSearchVisible = true;
+ component.commentSearchVisible = true;
+ component.listOfDisplayUser = [userA];
+
+ component.reset();
+
+ expect(component.nameSearchValue).toBe("");
+ expect(component.emailSearchValue).toBe("");
+ expect(component.commentSearchValue).toBe("");
+ expect(component.nameSearchVisible).toBe(false);
+ expect(component.emailSearchVisible).toBe(false);
+ expect(component.commentSearchVisible).toBe(false);
+ expect(component.listOfDisplayUser).toEqual([userA, userB]);
+ });
+
+ it("updateRole edits only the role and persists it", () => {
+ component.userList = [userA];
+ component.listOfDisplayUser = [userA];
+
+ component.updateRole(userA, Role.ADMIN);
+
+ expect(adminUserServiceSpy.updateUser).toHaveBeenCalledWith(
+ userA.uid,
+ userA.name,
+ userA.email,
+ Role.ADMIN,
+ userA.comment
+ );
+ expect(component.userList.find(u => u.uid ===
userA.uid)?.role).toBe(Role.ADMIN);
+ });
+
+ it("isUserActive reflects the recent-login window", () => {
+ const nowSeconds = Math.floor(Date.now() / 1000);
+ expect(component.isUserActive({ ...userA, lastLogin: nowSeconds } as
User)).toBe(true);
+ expect(component.isUserActive({ ...userA, lastLogin: nowSeconds - 100000 }
as User)).toBe(false);
+ expect(component.isUserActive({ ...userA, lastLogin: undefined } as
User)).toBe(false);
+ });
Review Comment:
Good catch — fixed in `b31520e2`. The test now derives the window from the
configured `activeTimeInMinutes`
(`TestBed.inject(GuiConfigService).env.activeTimeInMinutes`) and checks a
`lastLogin` just inside and just outside it, so it no longer depends on the
literal and stays correct if the default changes.
##########
frontend/src/app/dashboard/component/admin/user/admin-user.component.spec.ts:
##########
@@ -18,23 +18,69 @@
*/
import { ComponentFixture, inject, TestBed } from "@angular/core/testing";
+import { of, throwError } from "rxjs";
import { AdminUserComponent } from "./admin-user.component";
import { UserService } from "../../../../common/service/user/user.service";
import { StubUserService } from
"../../../../common/service/user/stub-user.service";
import { AdminUserService } from
"../../../service/admin/user/admin-user.service";
+import { FeedbackService } from
"../../../service/user/feedback/feedback.service";
+import { Role, User } from "../../../../common/type/user";
+import { UserQuotaComponent } from
"../../user/user-quota/user-quota.component";
+import { FeedbackComponent } from "../../user/feedback/feedback.component";
import { HttpClientTestingModule, HttpTestingController } from
"@angular/common/http/testing";
import { FormsModule } from "@angular/forms";
import { NzDropDownModule } from "ng-zorro-antd/dropdown";
-import { NzModalModule } from "ng-zorro-antd/modal";
+import { NzModalModule, NzModalService } from "ng-zorro-antd/modal";
+import { NzMessageService } from "ng-zorro-antd/message";
import { commonTestProviders } from "../../../../common/testing/test-utils";
+const userA: User = {
+ uid: 1,
+ name: "Alice",
+ email: "[email protected]",
+ role: Role.REGULAR,
+ comment: "c1",
+ joiningReason: "r1",
+ accountCreation: 1000,
+ lastLogin: 2000,
+};
+
+const userB: User = {
+ uid: 2,
+ name: "Bob",
+ email: "[email protected]",
+ role: Role.ADMIN,
+ comment: "c2",
+ joiningReason: "r2",
+ accountCreation: 3000,
+};
+
describe("AdminUserComponent", () => {
let component: AdminUserComponent;
let fixture: ComponentFixture<AdminUserComponent>;
+ let adminUserServiceSpy: {
+ getUserList: ReturnType<typeof vi.fn>;
+ addUser: ReturnType<typeof vi.fn>;
+ updateUser: ReturnType<typeof vi.fn>;
+ };
+ let feedbackServiceSpy: { getFeedbackCounts: ReturnType<typeof vi.fn> };
+
beforeEach(async () => {
+ adminUserServiceSpy = {
+ getUserList: vi.fn().mockReturnValue(of([])),
+ addUser: vi.fn().mockReturnValue(of(undefined)),
+ updateUser: vi.fn().mockReturnValue(of(undefined)),
+ };
+ feedbackServiceSpy = { getFeedbackCounts: vi.fn().mockReturnValue(of([]))
};
Review Comment:
Added `afterEach(() => vi.restoreAllMocks())` in `b31520e2`. For what it's
worth, these spies are installed on per-test service instances (Angular's
`TestBed` recreates the injector between tests), so they don't actually leak
across tests here — but the explicit restore is good hygiene and matches the
existing pattern in `app.component.spec.ts`.
--
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]