Skip to content

tests: Added unit tests for user password command#687

Open
rkcoder101 wants to merge 2 commits intogoharbor:mainfrom
rkcoder101:test/user-password
Open

tests: Added unit tests for user password command#687
rkcoder101 wants to merge 2 commits intogoharbor:mainfrom
rkcoder101:test/user-password

Conversation

@rkcoder101
Copy link
Contributor

@rkcoder101 rkcoder101 commented Feb 7, 2026

Description

This PR introduces unit tests for the user password command (cmd/harbor/root/user/password.go)

Relates to #591

Is a sub-part of #653

Note

No changes have been done to the core logic of the application, only a little refactoring for the purpose of writing some nice and clean test code :)

Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
Copilot AI review requested due to automatic review settings February 7, 2026 09:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds unit tests around the user password command flow and refactors the command implementation to make the logic injectable/testable without changing the underlying API behavior.

Changes:

  • Refactored UserPasswordChangeCmd internals into a ChangePassword function driven by a UserPasswordChanger interface.
  • Added unit tests for password change scenarios using a mock UserPasswordChanger.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
cmd/harbor/root/user/password.go Refactors password reset command to use an injectable interface and extracted ChangePassword for testability.
cmd/harbor/root/user/password_test.go Adds unit tests for password change flow using a mock implementation and captured log output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to +31
type MockUserPasswordChanger struct {
id map[string]int64
passwords map[int64]string
userCnt int
expectAuthError bool
}
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MockUserPasswordChanger.userCnt is never read in the test helper; keeping unused fields makes the mock harder to understand/maintain. Consider removing it, or using it (e.g., to drive GetUserIDFromUser behavior) so it provides value.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is used when populating the users in the init function

Comment on lines +95 to +99
setup: func() *MockUserPasswordChanger {
m := initMockUserPasswordChanger(5, false)
m.id["promptuser"] = 999
m.passwords[999] = "InitialPass123"
return m
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the interactive prompt test setup, m.id["promptuser"] = 999 is unused because GetUserIDFromUser() always returns 999 and never consults m.id. Consider either removing these unused setup lines or updating GetUserIDFromUser() to derive the returned ID from the mock state to better reflect the intended scenario.

Copilot uses AI. Check for mistakes.
Use: "password",
Short: "Reset user password by name or id",
Long: "Allows admin to reset the password for a specified user or select interactively if no username is provided.",
Args: cobra.MinimumNArgs(0),
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Args: cobra.MinimumNArgs(0) allows multiple positional args, but ChangePassword only uses args[0], silently ignoring the rest. Consider using cobra.MaximumNArgs(1) (or ExactArgs(1) if username is required) to prevent confusing/ignored input.

Suggested change
Args: cobra.MinimumNArgs(0),
Args: cobra.MaximumNArgs(1),

Copilot uses AI. Check for mistakes.
Comment on lines 81 to 90
func UserPasswordChangeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "password",
Short: "Reset user password by name or id",
Long: "Allows admin to reset the password for a specified user or select interactively if no username is provided.",
Args: cobra.MinimumNArgs(0),
Run: func(cmd *cobra.Command, args []string) {
var userId int64
var err error
resetView := &reset.PasswordChangeView{
NewPassword: opts.NewPassword,
ConfirmPassword: opts.ConfirmPassword,
}

if len(args) > 0 {
userId, err = api.GetUsersIdByName(args[0])
if err != nil {
log.Errorf("failed to get user id for '%s': %v", args[0], err)
return
}
if userId == 0 {
log.Errorf("User with name '%s' not found", args[0])
return
}
} else {
userId = prompt.GetUserIdFromUser()
}

reset.ChangePasswordView(resetView)

err = api.ResetPassword(userId, opts)
if err != nil {
if isUnauthorizedError(err) {
log.Error("Permission denied: Admin privileges are required to execute this command.")
} else {
log.Errorf("failed to reset user password: %v", err)
}
}
d := &DefaultUserPasswordChanger{}
ChangePassword(args, d)
},
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says the tests are for the "user list" command, but the changed files and new tests are for the user password command (cmd/harbor/root/user/password.go). Please update the PR description to match the actual scope to avoid confusion during review/release notes.

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +64
if len(args) > 0 {
userID, err = passwordChanger.GetUserIDByName(args[0])
if err != nil {
log.Errorf("failed to get user id for '%s': %v", args[0], err)
return
}
if userID == 0 {
log.Errorf("User with name '%s' not found", args[0])
return
}
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage gap: the production implementation api.GetUsersIdByName returns (0, nil) when the user is not found, and ChangePassword has a dedicated userID == 0 branch. The tests only cover the "not found" case via an error return, so the userID == 0 branch is currently untested.

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +78
err = passwordChanger.ResetPassword(userID, *resetView)
if err != nil {
if isUnauthorizedError(err) {
log.Error("Permission denied: Admin privileges are required to execute this command.")
} else {
log.Errorf("failed to reset user password: %v", err)
}
}
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage gap: there is no test asserting the non-403 error path for ResetPassword (the failed to reset user password log branch). Adding a test case where ResetPassword returns a non-"403" error would ensure this branch remains correct.

Copilot uses AI. Check for mistakes.
@codecov
Copy link

codecov bot commented Feb 7, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 7.31%. Comparing base (60ad0bd) to head (2a7be3c).
⚠️ Report is 83 commits behind head on main.

Files with missing lines Patch % Lines
cmd/harbor/root/user/password.go 50.00% 14 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             main    #687      +/-   ##
=========================================
- Coverage   10.99%   7.31%   -3.68%     
=========================================
  Files         173     260      +87     
  Lines        8671   12856    +4185     
=========================================
- Hits          953     940      -13     
- Misses       7612   11806    +4194     
- Partials      106     110       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rkcoder101 rkcoder101 mentioned this pull request Feb 7, 2026
5 tasks
Signed-off-by: Rayyan Khan <rayyanrehman101@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant