main 6af0a61

user_test.go RawHistoryFolder

1package user
2
3import (
4	"testing"
5)
6
7func TestNewUser_Valid(t *testing.T) {
8	user, err := NewUser("testuser", "/bin/bash")
9
10	if err != nil {
11		t.Fatalf("expected no error, got %v", err)
12	}
13
14	if user.Username() != "testuser" {
15		t.Errorf("expected username testuser")
16	}
17
18	if user.Shell() != "/bin/bash" {
19		t.Errorf("expected shell /bin/bash")
20	}
21
22	if user.Home() != "/home/testuser" {
23		t.Errorf("expected home /home/testuser")
24	}
25}
26
27func TestNewUser_InvalidUsername(t *testing.T) {
28	tests := []struct {
29		name      string
30		username  string
31		shouldErr bool
32	}{
33		{"empty username", "", true},
34		{"too short", "ab", true},
35		{"too long", "a" + string(make([]byte, 100)), true},
36		{"starts with digit", "1user", true},
37		{"uppercase", "User", true},
38		{"contains space", "test user", true},
39		{"valid simple", "testuser", false},
40		{"with underscore", "test_user", false},
41		{"with hyphen", "test-user", false},
42		{"with digit", "user123", false},
43	}
44
45	for _, tt := range tests {
46		t.Run(tt.name, func(t *testing.T) {
47			_, err := NewUser(tt.username, "/bin/bash")
48			if (err != nil) != tt.shouldErr {
49				t.Errorf("expected error=%v, got %v", tt.shouldErr, err)
50			}
51		})
52	}
53}
54
55func TestNewUser_InvalidShell(t *testing.T) {
56	tests := []struct {
57		name      string
58		shell     string
59		shouldErr bool
60	}{
61		{"empty shell", "", true},
62		{"relative path", "bash", true},
63		{"valid bash", "/bin/bash", false},
64		{"valid zsh", "/bin/zsh", false},
65		{"valid sh", "/bin/sh", false},
66		{"valid fish", "/bin/fish", false},
67	}
68
69	for _, tt := range tests {
70		t.Run(tt.name, func(t *testing.T) {
71			_, err := NewUser("testuser", tt.shell)
72			if (err != nil) != tt.shouldErr {
73				t.Errorf("expected error=%v, got %v", tt.shouldErr, err)
74			}
75		})
76	}
77}
78
79func TestUser_AddGroup(t *testing.T) {
80	user, _ := NewUser("testuser", "/bin/bash")
81
82	err := user.AddGroup("wheel")
83	if err != nil {
84		t.Errorf("unexpected error: %v", err)
85	}
86
87	if !user.HasGroup("wheel") {
88		t.Error("expected user to be in wheel group")
89	}
90}
91
92func TestUser_AddGroup_Duplicate(t *testing.T) {
93	user, _ := NewUser("testuser", "/bin/bash")
94
95	if err := user.AddGroup("wheel"); err != nil {
96		t.Fatalf("expected no error, got %v", err)
97	}
98	err := user.AddGroup("wheel")
99
100	if err == nil {
101		t.Error("expected error for duplicate group")
102	}
103}
104
105func TestUser_AddGroup_Empty(t *testing.T) {
106	user, _ := NewUser("testuser", "/bin/bash")
107
108	err := user.AddGroup("")
109
110	if err == nil {
111		t.Error("expected error for empty group")
112	}
113}
114
115func TestUser_HasGroup(t *testing.T) {
116	user, _ := NewUser("testuser", "/bin/bash")
117
118	if user.HasGroup("wheel") {
119		t.Error("expected user not in wheel group")
120	}
121
122	if err := user.AddGroup("wheel"); err != nil {
123		t.Fatalf("expected no error, got %v", err)
124	}
125
126	if !user.HasGroup("wheel") {
127		t.Error("expected user in wheel group")
128	}
129}
130
131func TestValidateUsername(t *testing.T) {
132	tests := []struct {
133		name      string
134		username  string
135		shouldErr bool
136	}{
137		{"valid", "testuser", false},
138		{"empty", "", true},
139		{"short", "ab", true},
140		{"long", "a" + string(make([]byte, 100)), true},
141		{"starts digit", "1test", true},
142		{"uppercase", "TestUser", true},
143		{"special", "test@user", true},
144	}
145
146	for _, tt := range tests {
147		t.Run(tt.name, func(t *testing.T) {
148			err := ValidateUsername(tt.username)
149			if (err != nil) != tt.shouldErr {
150				t.Errorf("expected error=%v, got %v", tt.shouldErr, err)
151			}
152		})
153	}
154}
155
156func TestNewCredentials_Valid(t *testing.T) {
157	creds, err := NewCredentials("userpass123", "rootpass456")
158
159	if err != nil {
160		t.Fatalf("expected no error, got %v", err)
161	}
162
163	if !creds.HasPassword() {
164		t.Error("expected to have password")
165	}
166}
167
168func TestNewCredentials_WeakPassword(t *testing.T) {
169	_, err := NewCredentials("wee", "rootpass456")
170
171	if err == nil {
172		t.Error("expected error for weak password")
173	}
174}
175
176func TestNewCredentials_SamePassword(t *testing.T) {
177	_, err := NewCredentials("samepass123", "samepass123")
178
179	if err == nil {
180		t.Error("expected error for same passwords")
181	}
182}
183
184func TestValidatePassword(t *testing.T) {
185	tests := []struct {
186		name      string
187		password  string
188		shouldErr bool
189	}{
190		{"empty", "", true},
191		{"too short", "sho", true},
192		{"valid", "validpass123", false},
193		{"long valid", "a" + string(make([]byte, 100)) + "x", false},
194		{"too long", "a" + string(make([]byte, 200)), true},
195	}
196
197	for _, tt := range tests {
198		t.Run(tt.name, func(t *testing.T) {
199			err := ValidatePassword(tt.password)
200			if (err != nil) != tt.shouldErr {
201				t.Errorf("expected error=%v, got %v", tt.shouldErr, err)
202			}
203		})
204	}
205}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 0

    ↑↓ moveenter openesc close