Branch data Line data Source code
1 [ + ]: 1 : /**
2 : 1 : * @module redis-users-test
3 : 1 : * @desc The leaderboard-api redis-users Users class testing module.
4 : 1 : * @version 1.0.0
5 : 1 : * @author Essam A. El-Sherif
6 : 1 : */
7 : 1 :
8 : 1 : /* Import node.js core modules */
9 : 1 : import assert from 'node:assert/strict';
10 : 1 : import runner from 'node:test';
11 : 1 : import { fileURLToPath } from 'node:url';
12 : 1 : import { dirname, join } from 'node:path';
13 : 1 :
14 : 1 : /* Import package dependencies */
15 : 1 : import redis from 'redis';
16 : 1 : import dotenv from 'dotenv';
17 : 1 :
18 : 1 : /* Import local dependencies */
19 : 1 : import { Users } from '../lib/redis-users.js';
20 : 1 :
21 : 1 : /* Emulate commonJS __filename and __dirname constants */
22 : 1 : const __filename = fileURLToPath(import.meta.url);
23 : 1 : const __dirname = dirname(__filename);
24 : 1 :
25 : 1 : /* Configure dotenv path to read the package .env file */
26 : 1 : dotenv.config({path: join(__dirname, '../.env')});
27 : 1 :
28 : 1 : /* Prepare test environment */
29 : 1 : const suites = new Map();
30 : 1 : let usersObj = null;
31 : 1 :
32 : 1 : /**
33 : 1 : * @func Main
34 : 1 : * @async
35 : 1 : * @desc The module entry point function.
36 : 1 : */
37 [ + ]: 1 : (async () => {
38 : 1 :
39 : 1 : let clientRd;
40 : 1 :
41 : 1 : /*
42 : 1 : * https://github.com/redis/node-redis
43 : 1 : *
44 : 1 : * Create a node-redis Client instance, or throws on failure.
45 : 1 : * Connect to Redis.
46 : 1 : * Since v4 of node-redis, the client does not automatically connect to the server.
47 : 1 : * Instead you need to run .connect() after creating the client or you will receive an error.
48 : 1 : */
49 : 1 : try{
50 : 1 : clientRd = redis.createClient({
51 : 1 : url: process.env.lb_connectRd,
52 : 1 : name: 'leaderboard-api-test'
53 : 1 : });
54 : 1 :
55 : 1 : await clientRd.connect();
56 : 1 : await clientRd.sendCommand(['FLUSHALL']);
57 : 1 :
58 : 1 : usersObj = new Users(clientRd, 'lb:user:');
59 : 1 : }
60 [ - ]: 1 : catch(err){ /* node:coverage disable */
61 : : console.error(err.message);
62 : : process.exit(1);
63 : : } /* node:coverage enable */
64 : 1 :
65 : 1 : loadTestData();
66 : 1 :
67 [ + ]: 1 : runner.after(async() => {
68 : 1 : await clientRd.sendCommand(['FLUSHALL']);
69 : 1 : await clientRd.quit();
70 : 1 : });
71 : 1 : nodeRunner(runner);
72 : 1 :
73 : 1 : })('Main Function');
74 : 1 :
75 : 1 : /**
76 : 1 : * @func loadTestData
77 : 1 : * @desc Load test data.
78 : 1 : */
79 [ + ]: 1 : function loadTestData(){
80 : 1 :
81 : 1 : let testData = null;
82 : 1 : let suiteDesc = '';
83 : 1 : let testObj = null;
84 : 1 :
85 : 1 : // TEST SUITE ### - Test Users Class
86 : 1 : suiteDesc = 'Test Users Class';
87 : 1 : suites.set(suiteDesc, []);
88 : 1 :
89 : 1 : // TEST ### - Test createUser(username, pwd) ... test#1
90 : 1 : testData = {};
91 : 1 :
92 : 1 : testObj = {
93 : 1 : usersMethod: usersObj.createUser,
94 : 1 : usersMethodArg: ['user@1', 'password-1'],
95 : 1 : usersMethodOut: {username: 'user@1', password: '********'},
96 : 1 : usersThrows: false,
97 : 1 : };
98 : 1 :
99 : 1 : testData.method = testMethod.bind(testObj);
100 : 1 : testData.desc = 'Test createUser(username, pwd) ... test#1';
101 : 1 :
102 : 1 : testData.skip = false;
103 : 1 : suites.get(suiteDesc).push(testData);
104 : 1 :
105 : 1 : // TEST ### - Test createUser(username, pwd) ... test#2
106 : 1 : testData = {};
107 : 1 :
108 : 1 : testObj = {
109 : 1 : usersMethod: usersObj.createUser,
110 : 1 : usersMethodArg: ['user@2', 'password-2'],
111 : 1 : usersMethodOut: {username: 'user@2', password: '********'},
112 : 1 : usersThrows: false,
113 : 1 : };
114 : 1 :
115 : 1 : testData.method = testMethod.bind(testObj);
116 : 1 : testData.desc = 'Test createUser(username, pwd) ... test#2';
117 : 1 :
118 : 1 : testData.skip = false;
119 : 1 : suites.get(suiteDesc).push(testData);
120 : 1 :
121 : 1 : // TEST ### - Test createUser(username, pwd) ... test#3
122 : 1 : testData = {};
123 : 1 :
124 : 1 : testObj = {
125 : 1 : usersMethod: usersObj.createUser,
126 : 1 : usersMethodArg: ['user@1', 'password-1'],
127 : 1 : usersMethodOut: null,
128 : 1 : usersThrows: 'username already exists',
129 : 1 : };
130 : 1 :
131 : 1 : testData.method = testMethod.bind(testObj);
132 : 1 : testData.desc = 'Test createUser(username, pwd) ... test#3';
133 : 1 :
134 : 1 : testData.skip = false;
135 : 1 : suites.get(suiteDesc).push(testData);
136 : 1 :
137 : 1 : // TEST ### - Test updateUser(username, pwd, newpwd) ... test#1
138 : 1 : testData = {};
139 : 1 :
140 : 1 : testObj = {
141 : 1 : usersMethod: usersObj.updateUser,
142 : 1 : usersMethodArg: ['user@1', 'password-1'],
143 : 1 : usersMethodOut: {username: 'user@1', password: '********'},
144 : 1 : usersThrows: false,
145 : 1 : };
146 : 1 :
147 : 1 : testData.method = testMethod.bind(testObj);
148 : 1 : testData.desc = 'Test updateUser(username, pwd, newpwd) ... test#1';
149 : 1 :
150 : 1 : testData.skip = false;
151 : 1 : suites.get(suiteDesc).push(testData);
152 : 1 :
153 : 1 : // TEST ### - Test updateUser(username, pwd, newpwd) ... test#2
154 : 1 : testData = {};
155 : 1 :
156 : 1 : testObj = {
157 : 1 : usersMethod: usersObj.updateUser,
158 : 1 : usersMethodArg: ['user@1', 'password-1', 'password-1'],
159 : 1 : usersMethodOut: {username: 'user@1', password: '********'},
160 : 1 : usersThrows: false,
161 : 1 : };
162 : 1 :
163 : 1 : testData.method = testMethod.bind(testObj);
164 : 1 : testData.desc = 'Test updateUser(username, pwd, newpwd) ... test#2';
165 : 1 :
166 : 1 : testData.skip = false;
167 : 1 : suites.get(suiteDesc).push(testData);
168 : 1 :
169 : 1 : // TEST ### - Test updateUser(username, pwd, newpwd) ... test#3
170 : 1 : testData = {};
171 : 1 :
172 : 1 : testObj = {
173 : 1 : usersMethod: usersObj.updateUser,
174 : 1 : usersMethodArg: ['user@x', 'password-1'],
175 : 1 : usersMethodOut: null,
176 : 1 : usersThrows: 'username does not exist',
177 : 1 : };
178 : 1 :
179 : 1 : testData.method = testMethod.bind(testObj);
180 : 1 : testData.desc = 'Test updateUser(username, pwd, newpwd) ... test#3';
181 : 1 :
182 : 1 : testData.skip = false;
183 : 1 : suites.get(suiteDesc).push(testData);
184 : 1 :
185 : 1 : // TEST ### - Test updateUser(username, pwd, newpwd) ... test#4
186 : 1 : testData = {};
187 : 1 :
188 : 1 : testObj = {
189 : 1 : usersMethod: usersObj.updateUser,
190 : 1 : usersMethodArg: ['user@1', 'password-x'],
191 : 1 : usersMethodOut: null,
192 : 1 : usersThrows: 'invalid password',
193 : 1 : };
194 : 1 :
195 : 1 : testData.method = testMethod.bind(testObj);
196 : 1 : testData.desc = 'Test updateUser(username, pwd, newpwd) ... test#4';
197 : 1 :
198 : 1 : testData.skip = false;
199 : 1 : suites.get(suiteDesc).push(testData);
200 : 1 :
201 : 1 : // TEST ### - Test deleteUser(username, pwd) ... test#1
202 : 1 : testData = {};
203 : 1 :
204 : 1 : testObj = {
205 : 1 : usersMethod: usersObj.deleteUser,
206 : 1 : usersMethodArg: ['user@2', 'password-2'],
207 : 1 : usersMethodOut: {username: 'user@2', password: '********'},
208 : 1 : usersThrows: false,
209 : 1 : };
210 : 1 :
211 : 1 : testData.method = testMethod.bind(testObj);
212 : 1 : testData.desc = 'Test deleteUser(username, pwd) ... test#1';
213 : 1 :
214 : 1 : testData.skip = false;
215 : 1 : suites.get(suiteDesc).push(testData);
216 : 1 :
217 : 1 : // TEST ### - Test deleteUser(username, pwd) ... test#2
218 : 1 : testData = {};
219 : 1 :
220 : 1 : testObj = {
221 : 1 : usersMethod: usersObj.deleteUser,
222 : 1 : usersMethodArg: ['user@2', 'password-2'],
223 : 1 : usersMethodOut: null,
224 : 1 : usersThrows: 'username does not exist',
225 : 1 : };
226 : 1 :
227 : 1 : testData.method = testMethod.bind(testObj);
228 : 1 : testData.desc = 'Test deleteUser(username, pwd) ... test#2';
229 : 1 :
230 : 1 : testData.skip = false;
231 : 1 : suites.get(suiteDesc).push(testData);
232 : 1 :
233 : 1 : // TEST ### - Test deleteUser(username, pwd) ... test#3
234 : 1 : testData = {};
235 : 1 :
236 : 1 : testObj = {
237 : 1 : usersMethod: usersObj.deleteUser,
238 : 1 : usersMethodArg: ['user@1', 'password-x'],
239 : 1 : usersMethodOut: null,
240 : 1 : usersThrows: 'invalid password',
241 : 1 : };
242 : 1 :
243 : 1 : testData.method = testMethod.bind(testObj);
244 : 1 : testData.desc = 'Test deleteUser(username, pwd) ... test#3';
245 : 1 :
246 : 1 : testData.skip = false;
247 : 1 : suites.get(suiteDesc).push(testData);
248 : 1 :
249 : 1 : // TEST ### - Test getUsers() ... test#1
250 : 1 : testData = {};
251 : 1 :
252 : 1 : testObj = {
253 : 1 : usersMethod: usersObj.getUsers,
254 : 1 : usersMethodArg: [],
255 : 1 : usersMethodOut: [{username: 'user@1', password: '********'}],
256 : 1 : usersThrows: false,
257 : 1 : };
258 : 1 :
259 : 1 : testData.method = testMethod.bind(testObj);
260 : 1 : testData.desc = 'Test getUsers() ... test#1';
261 : 1 :
262 : 1 : testData.skip = false;
263 : 1 : suites.get(suiteDesc).push(testData);
264 : 1 : }
265 : 1 :
266 : 1 : /**
267 : 1 : * @func nodeRunner
268 : 1 : * @param {object} runner - The node core module 'node:test' object.
269 : 1 : * @desc Carry out the loaded tests using node test runner.
270 : 1 : */
271 [ + ]: 1 : function nodeRunner(runner){
272 : 1 :
273 : 1 : for(let [suiteDesc, suiteTests] of suites){
274 [ + ]: 1 : runner.suite(suiteDesc, () => {
275 [ + ]: 1 : for(let cmdObj of suiteTests){
276 [ + ]: 11 : runner.test(cmdObj.desc, {skip: cmdObj.skip}, async () => {
277 : 11 : await cmdObj.method();
278 : 11 : });
279 : 11 : }
280 : 1 : });
281 : 1 : }
282 : 1 : }
283 : 1 :
284 : 1 : /**
285 : 1 : * @func
286 : 1 : * @async
287 : 1 : * @desc Carries out the assertions tests.
288 : 1 : */
289 [ + ]: 11 : async function testMethod(){
290 : 11 :
291 [ + ]: 11 : if(this.usersThrows){
292 : 5 : try{
293 [ - ]: 5 : await this.usersMethod.apply(usersObj, this.usersMethodArg); /* node:coverage disable */
294 : : assert(false);
295 : : } /* node:coverage enable */
296 : 5 : catch(err){
297 : 5 : if(typeof this.usersThrows === 'string'){
298 : 5 : assert.strictEqual(err.message, this.usersThrows);
299 : 5 : }
300 : 5 : }
301 [ + ]: 5 : }
302 : 6 : else{
303 : 6 : let actOut = await this.usersMethod.apply(usersObj, this.usersMethodArg);
304 : 6 :
305 : 6 : if(typeof actOut === 'object'){
306 [ + ]: 6 : if(Array.isArray(actOut)){
307 [ + ]: 1 : actOut.forEach((obj) => delete obj.timestamp);
308 [ + ]: 1 : }
309 : 5 : else{
310 : 5 : delete actOut.timestamp;
311 : 5 : }
312 : 6 : assert.deepStrictEqual(actOut, this.usersMethodOut);
313 : 6 : }
314 : 6 : }
315 : 11 : }
|