Repository navigation
Expand file tree
/
Copy pathusernameService.test.js
More file actions
223 lines (181 loc) · 7.85 KB
/
Copy pathusernameService.test.js
File metadata and controls
223 lines (181 loc) · 7.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/**
* __tests__/usernameService.test.js
* Unit tests for usernameService (issue #533).
*
* Tests username registration, uniqueness, and resolution to Stellar address.
*/
"use strict";
const usernameService = require("../src/services/usernameService");
const KEY_A = "G" + "A".repeat(55); // 56 chars
const KEY_B = "G" + "B".repeat(55); // 56 chars
const KEY_C = "G" + "C".repeat(55); // 56 chars
describe("usernameService", () => {
beforeEach(() => {
// Clear in-memory storage before each test
usernameService.usernameMap?.clear?.();
});
describe("registerUsername", () => {
it("registering a new username succeeds", () => {
const result = usernameService.registerUsername("alice123", KEY_A);
expect(result.username).toBe("alice123");
expect(result.publicKey).toBe(KEY_A);
});
it("registering a taken username is rejected", () => {
usernameService.registerUsername("alice123", KEY_A);
expect(() => {
usernameService.registerUsername("alice123", KEY_B);
}).toThrow("Username already registered");
});
it("registering with an already registered public key is rejected", () => {
usernameService.registerUsername("alice123", KEY_A);
expect(() => {
usernameService.registerUsername("bob456", KEY_A);
}).toThrow("Public key already registered to another username");
});
it("rejects invalid username format", () => {
expect(() => usernameService.registerUsername("a", KEY_A)).toThrow();
expect(() => usernameService.registerUsername("user with spaces", KEY_A)).toThrow();
});
it("rejects invalid public key format", () => {
expect(() => usernameService.registerUsername("alice123", "invalid_key")).toThrow();
});
});
describe("resolveUsername", () => {
beforeEach(() => {
usernameService.registerUsername("alice123", KEY_A);
});
it("resolves a registered username", () => {
const result = usernameService.resolveUsername("alice123");
expect(result.username).toBe("alice123");
expect(result.publicKey).toBe(KEY_A);
});
it("throws error for non-existent username", () => {
expect(() => usernameService.resolveUsername("nonexistent")).toThrow("Username not found");
});
it("throws error with 404 status for unregistered username", () => {
try {
usernameService.resolveUsername("unknownuser");
fail("Should have thrown error");
} catch (error) {
expect(error.status).toBe(404);
expect(error.message).toBe("Username not found");
}
});
it("throws error for invalid username format", () => {
expect(() => usernameService.resolveUsername("ab")).toThrow();
});
it("throws error for missing username", () => {
expect(() => usernameService.resolveUsername(null)).toThrow("Username is required");
});
});
describe("getAllUsernames", () => {
it("returns all registered usernames", () => {
usernameService.registerUsername("alice123", KEY_A);
usernameService.registerUsername("bob456", KEY_B);
const result = usernameService.getAllUsernames();
expect(result).toHaveLength(2);
expect(result).toEqual([
{ username: "alice123", publicKey: KEY_A },
{ username: "bob456", publicKey: KEY_B },
]);
});
it("returns empty array when no usernames are registered", () => {
const result = usernameService.getAllUsernames();
expect(result).toHaveLength(0);
expect(result).toEqual([]);
});
});
describe("removeUsername", () => {
beforeEach(() => {
usernameService.registerUsername("alice123", KEY_A);
});
it("removes an existing username", () => {
const result = usernameService.removeUsername("alice123");
expect(result.username).toBe("alice123");
expect(() => usernameService.resolveUsername("alice123")).toThrow("Username not found");
});
it("throws error when removing non-existent username", () => {
expect(() => usernameService.removeUsername("nonexistent")).toThrow("Username not found");
});
it("throws error with 404 status for non-existent username", () => {
try {
usernameService.removeUsername("unknownuser");
fail("Should have thrown error");
} catch (error) {
expect(error.status).toBe(404);
expect(error.message).toBe("Username not found");
}
});
it("throws error for invalid username format", () => {
expect(() => usernameService.removeUsername("ab")).toThrow();
});
it("throws error for missing username", () => {
expect(() => usernameService.removeUsername(null)).toThrow("Username is required");
});
});
describe("validateUsername", () => {
it("accepts valid usernames", () => {
expect(() => usernameService.validateUsername("alice")).not.toThrow();
expect(() => usernameService.validateUsername("bob123")).not.toThrow();
expect(() => usernameService.validateUsername("user123456789012345")).not.toThrow();
});
it("rejects usernames that are too short", () => {
expect(() => usernameService.validateUsername("ab")).toThrow(
"Username must be 3-20 characters long and contain only letters and numbers"
);
});
it("rejects usernames that are too long", () => {
expect(() => usernameService.validateUsername("user12345678901234567")).toThrow(
"Username must be 3-20 characters long and contain only letters and numbers"
);
});
it("rejects usernames with special characters", () => {
expect(() => usernameService.validateUsername("user_name")).toThrow(
"Username must be 3-20 characters long and contain only letters and numbers"
);
expect(() => usernameService.validateUsername("user@name")).toThrow(
"Username must be 3-20 characters long and contain only letters and numbers"
);
});
it("rejects usernames with spaces", () => {
expect(() => usernameService.validateUsername("user name")).toThrow(
"Username must be 3-20 characters long and contain only letters and numbers"
);
});
it("rejects null/undefined username", () => {
expect(() => usernameService.validateUsername(null)).toThrow("Username is required");
expect(() => usernameService.validateUsername(undefined)).toThrow("Username is required");
});
});
describe("validatePublicKey", () => {
it("accepts valid Stellar public keys", () => {
expect(() => usernameService.validatePublicKey(KEY_A)).not.toThrow();
expect(() => usernameService.validatePublicKey(KEY_B)).not.toThrow();
});
it("rejects public keys with wrong prefix", () => {
expect(() =>
usernameService.validatePublicKey("SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF")
).toThrow("Invalid Stellar public key format");
expect(() =>
usernameService.validatePublicKey("MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF")
).toThrow("Invalid Stellar public key format");
});
it("rejects public keys with incorrect length", () => {
expect(() =>
usernameService.validatePublicKey("GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWH")
).toThrow("Invalid Stellar public key format");
expect(() =>
usernameService.validatePublicKey("GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHFA")
).toThrow("Invalid Stellar public key format");
});
it("rejects public keys with invalid characters", () => {
expect(() =>
usernameService.validatePublicKey("GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWH!")
).toThrow("Invalid Stellar public key format");
});
it("rejects null/undefined public key", () => {
expect(() => usernameService.validatePublicKey(null)).toThrow("Public key is required");
expect(() => usernameService.validatePublicKey(undefined)).toThrow("Public key is required");
});
});
});