Skip to content

Commit d22ee74

Browse files
committed
refactor: 💡 Server API tests minor refactoring
1 parent 6b6ec20 commit d22ee74

File tree

3 files changed

+125
-20
lines changed

3 files changed

+125
-20
lines changed

‎src/node/db/users.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ export interface UsersDbOptions {
4343
prefix: string;
4444
}
4545

46+
/**
47+
* Class that implements an API to the users records storage
48+
*
49+
* @export
50+
* @class UsersDb
51+
*/
4652
export class UsersDb {
4753
/** Storage instance for persisting the state of the API server */
4854
storage: Storage;
@@ -54,12 +60,12 @@ export class UsersDb {
5460
* Initializes an instance of UsersDb with given options.
5561
*
5662
* @param {UsersDbOptions} options
57-
* @memberof NodeApiServer
63+
* @memberof UsersDb
5864
*/
5965
constructor(options: UsersDbOptions) {
6066
const { storage, prefix } = options;
6167

62-
// TODO Validate NodeApiServerOptions
68+
// TODO Validate UsersDbOptions
6369

6470
this.prefix = `${prefix}_api_users_`;
6571
this.storage = storage;
@@ -77,18 +83,6 @@ export class UsersDb {
7783
return await hash(password, 10);
7884
}
7985

80-
/**
81-
* Generates a prefixed login key
82-
*
83-
* @private
84-
* @param {string} login The login for which the key is generated
85-
* @returns {string} The prefixed login key
86-
* @memberof UsersDb
87-
*/
88-
private loginKey(login: string): string {
89-
return `${this.prefix}${login}`;
90-
}
91-
9286
/**
9387
* Retrieves the user with the given login from storage.
9488
*
@@ -98,7 +92,7 @@ export class UsersDb {
9892
* @memberof UsersDb
9993
*/
10094
async get(login: string): Promise<User> {
101-
const user = await this.storage.get<User>(this.loginKey(login));
95+
const user = await this.storage.get<User>(`${this.prefix}${login}`);
10296

10397
if (!user) {
10498
throw new Error(`User ${login} not found`);
@@ -118,15 +112,15 @@ export class UsersDb {
118112
* @memberof UsersDb
119113
*/
120114
async add(login: string, password: string, isAdmin = false): Promise<void> {
121-
const knownUser = await this.storage.get<User>(this.loginKey(login));
115+
const knownUser = await this.storage.get<User>(`${this.prefix}${login}`);
122116

123117
// Check if the user already exists
124118
if (knownUser) {
125119
throw new Error(`User ${login} already exists`);
126120
}
127121

128122
// Save the user into the storage
129-
await this.storage.set<User>(this.loginKey(login), {
123+
await this.storage.set<User>(`${this.prefix}${login}`, {
130124
login,
131125
hashedPassword: await UsersDb.hashPassword(password),
132126
isAdmin,
@@ -141,7 +135,7 @@ export class UsersDb {
141135
* @memberof UsersDb
142136
*/
143137
async set(user: User): Promise<void> {
144-
await this.storage.set<User>(this.loginKey(user.login), user);
138+
await this.storage.set<User>(`${this.prefix}${user.login}`, user);
145139
}
146140

147141
/**
@@ -153,7 +147,7 @@ export class UsersDb {
153147
* @memberof UsersDb
154148
*/
155149
async delete(login: string): Promise<void> {
156-
const deleted = await this.storage.delete(this.loginKey(login));
150+
const deleted = await this.storage.delete(`${this.prefix}${login}`);
157151

158152
if (!deleted) {
159153
throw new Error(`Unable to delete user ${login}`);

‎test/node.api.nodeApiServer.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ describe('NodeApiServer', () => {
4545

4646
beforeAll(async () => {
4747
options = {
48-
storage: await createInitializer()(),
48+
storage: await createInitializer({
49+
scope: 'users',
50+
})(),
4951
prefix: 'test',
5052
port: 3456,
5153
secret: 'secret',

‎test/node.db.users.spec.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { describe, beforeAll, it, expect } from './setup.js';
2+
import { createInitializer } from '../src/storage/memory.js';
3+
import {
4+
UsersDb,
5+
UsersDbOptions,
6+
User,
7+
comparePassword,
8+
} from '../src/node/db/users.js';
9+
10+
describe('Node.API.Db', () => {
11+
const password = 'password';
12+
let userDb: UsersDb;
13+
let testUser: User;
14+
15+
beforeAll(async () => {
16+
const options: UsersDbOptions = {
17+
storage: await createInitializer({
18+
scope: 'users',
19+
})(),
20+
prefix: 'test',
21+
};
22+
userDb = new UsersDb(options);
23+
testUser = {
24+
login: 'testUser',
25+
hashedPassword: await UsersDb.hashPassword('password'),
26+
};
27+
});
28+
29+
describe('#add', () => {
30+
it('should add a new user', async () => {
31+
await userDb.add(testUser.login, password);
32+
const user = await userDb.get(testUser.login);
33+
expect(user.login).to.be.eq(testUser.login);
34+
expect(await comparePassword(password, user.hashedPassword)).to.be.true;
35+
});
36+
37+
it('should throw an error when trying to add an existing user', async () => {
38+
let error = null;
39+
try {
40+
await userDb.add(testUser.login, password);
41+
} catch (err) {
42+
error = err;
43+
}
44+
expect(error).to.be.an('Error');
45+
expect((error as Error).message).to.be.eq(
46+
`User ${testUser.login} already exists`,
47+
);
48+
});
49+
});
50+
51+
describe('#get', () => {
52+
it('should get a user', async () => {
53+
const user = await userDb.get(testUser.login);
54+
expect(user.login).to.be.eq(testUser.login);
55+
expect(await comparePassword(password, user.hashedPassword)).to.be.true;
56+
});
57+
58+
it('should throw an error when trying to get a non-existent user', async () => {
59+
let error = null;
60+
try {
61+
await userDb.get('nonExistentUser');
62+
} catch (err) {
63+
error = err;
64+
}
65+
expect(error).to.be.an('Error');
66+
expect((error as Error).message).to.be.eq(
67+
'User nonExistentUser not found',
68+
);
69+
});
70+
});
71+
72+
describe('#set', () => {
73+
it('should update a user', async () => {
74+
const updatedUser = { ...testUser, jwt: 'jwtToken' };
75+
await userDb.set(updatedUser);
76+
const user = await userDb.get(testUser.login);
77+
expect(user).to.deep.equal(updatedUser);
78+
});
79+
});
80+
81+
describe('#delete', () => {
82+
it('should delete a user', async () => {
83+
await userDb.delete(testUser.login);
84+
let error = null;
85+
try {
86+
await userDb.get(testUser.login);
87+
} catch (err) {
88+
error = err;
89+
}
90+
expect(error).to.be.an('Error');
91+
expect((error as Error).message).to.be.eq(
92+
`User ${testUser.login} not found`,
93+
);
94+
});
95+
96+
it('should throw an error when trying to delete a non-existent user', async () => {
97+
let error = null;
98+
try {
99+
await userDb.delete('nonExistentUser');
100+
} catch (err) {
101+
error = err;
102+
}
103+
expect(error).to.be.an('Error');
104+
expect((error as Error).message).to.be.eq(
105+
'Unable to delete user nonExistentUser',
106+
);
107+
});
108+
});
109+
});

0 commit comments

Comments
 (0)