Branch data Line data Source code
1 [ + ]: 1 : /**
2 : 1 : * @module score-route-test
3 : 1 : * @desc The leaderboard-api score route 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 fs from 'node:fs';
11 : 1 : import http from 'node:http';
12 : 1 : import https from 'node:https';
13 : 1 : import runner from 'node:test';
14 : 1 : import { fileURLToPath } from 'node:url';
15 : 1 : import { dirname, join } from 'node:path';
16 : 1 :
17 : 1 : /* Import package dependencies */
18 : 1 : import dotenv from 'dotenv';
19 : 1 :
20 : 1 : /* Import local dependencies */
21 : 1 : import { TestData } from './test-data.js';
22 : 1 :
23 : 1 : /* Emulate commonJS __filename and __dirname constants */
24 : 1 : const __filename = fileURLToPath(import.meta.url);
25 : 1 : const __dirname = dirname(__filename);
26 : 1 :
27 : 1 : /* Configure dotenv path to read the package .env file */
28 : 1 : dotenv.config({path: join(__dirname, '../.env')});
29 : 1 :
30 : 1 : /* Prepare test environment */
31 : 1 : const suites = new Map();
32 : 1 :
33 : 1 : const url = new URL('http://server');
34 : 1 :
35 : 1 : url.host = process.env.lb_serverHost;
36 : 1 : url.port = process.env.lb_serverPort;
37 : 1 : url.pathname = process.env.lb_serverPath;
38 : 1 :
39 : 1 : if(process.env.lb_serverProtocol === 'https'){
40 : 1 : url.protocol = 'https';
41 : 1 : }
42 : 1 : const baseUrl = `${url.href}/score`;
43 : 1 :
44 : 1 : let testUsers = null;
45 : 1 :
46 : 1 : /**
47 : 1 : * @func Main
48 : 1 : * @async
49 : 1 : * @desc The module entry point function.
50 : 1 : */
51 [ + ]: 1 : (async () => {
52 : 1 : const testData = new TestData();
53 : 1 : testUsers = testData.testUsers;
54 : 1 :
55 : 1 : await testData.unregisterTestUsers();
56 : 1 : await testData.registerTestUsers();
57 : 1 :
58 : 1 : loadTestData();
59 : 1 :
60 [ + ]: 1 : runner.after(async() => {
61 : 1 : await testData.unregisterTestUsers();
62 : 1 : });
63 : 1 : nodeRunner(runner);
64 : 1 :
65 : 1 : })('Main Function');
66 : 1 :
67 : 1 : /**
68 : 1 : * @func loadTestData
69 : 1 : * @desc Load test data.
70 : 1 : */
71 [ + ]: 1 : function loadTestData(){
72 : 1 :
73 : 1 : let testData = null;
74 : 1 : let suiteDesc = '';
75 : 1 : let testObj = null;
76 : 1 :
77 : 1 : // TEST SUITE ### - Test Score Route - addUserScore
78 : 1 : suiteDesc = 'Test Score Route - addUserScore';
79 : 1 : suites.set(suiteDesc, []);
80 : 1 :
81 : 1 : // TEST ### - Test addUserScore invalid ... test#1
82 : 1 : testData = {};
83 : 1 :
84 : 1 : testObj = {
85 : 1 : reqMethod: 'POST',
86 : 1 : reqAuth: undefined,
87 : 1 : reqBody: undefined,
88 : 1 : resCode: 401,
89 : 1 : resBody: 'Authorization Error: No authorization token was found',
90 : 1 : };
91 : 1 :
92 : 1 : testData.method = testMethod.bind(testObj);
93 : 1 : testData.desc = 'Test addUserScore invalid ... test#1';
94 : 1 :
95 : 1 : testData.skip = false;
96 : 1 : suites.get(suiteDesc).push(testData);
97 : 1 :
98 : 1 : // TEST ### - Test addUserScore invalid ... test#2
99 : 1 : testData = {};
100 : 1 :
101 : 1 : testObj = {
102 : 1 : reqMethod: 'POST',
103 : 1 : reqAuth: testUsers[0].token,
104 : 1 : reqBody: undefined,
105 : 1 : resCode: 400,
106 : 1 : resBody: 'Submission Error: none or invalid request payload',
107 : 1 : };
108 : 1 :
109 : 1 : testData.method = testMethod.bind(testObj);
110 : 1 : testData.desc = 'Test addUserScore invalid ... test#2';
111 : 1 :
112 : 1 : testData.skip = false;
113 : 1 : suites.get(suiteDesc).push(testData);
114 : 1 :
115 : 1 : // TEST ### - Test addUserScore invalid ... test#3
116 : 1 : testData = {};
117 : 1 :
118 : 1 : testObj = {
119 : 1 : reqMethod: 'POST',
120 : 1 : reqAuth: testUsers[0].token,
121 : 1 : reqBody: {},
122 : 1 : resCode: 400,
123 : 1 : resBody: 'Submission Error: none or invalid request payload',
124 : 1 : };
125 : 1 :
126 : 1 : testData.method = testMethod.bind(testObj);
127 : 1 : testData.desc = 'Test addUserScore invalid ... test#3';
128 : 1 :
129 : 1 : testData.skip = false;
130 : 1 : suites.get(suiteDesc).push(testData);
131 : 1 :
132 : 1 : // TEST ### - Test addUserScore invalid ... test#4
133 : 1 : testData = {};
134 : 1 :
135 : 1 : testObj = {
136 : 1 : reqMethod: 'POST',
137 : 1 : reqAuth: testUsers[0].token,
138 : 1 : reqBody: 'XXXXXXX',
139 : 1 : resCode: 400,
140 : 1 : resBody: 'Submission Error: none or invalid request payload',
141 : 1 : };
142 : 1 :
143 : 1 : testData.method = testMethod.bind(testObj);
144 : 1 : testData.desc = 'Test addUserScore invalid ... test#4';
145 : 1 :
146 : 1 : testData.skip = false;
147 : 1 : suites.get(suiteDesc).push(testData);
148 : 1 :
149 : 1 : // TEST ### - Test addUserScore invalid ... test#5
150 : 1 : testData = {};
151 : 1 :
152 : 1 : testObj = {
153 : 1 : reqMethod: 'POST',
154 : 1 : reqAuth: testUsers[0].token,
155 : 1 : reqBody: {activity: 'activity-1'},
156 : 1 : resCode: 400,
157 : 1 : resBody: 'Submission Error: no score given',
158 : 1 : };
159 : 1 :
160 : 1 : testData.method = testMethod.bind(testObj);
161 : 1 : testData.desc = 'Test addUserScore invalid ... test#5';
162 : 1 :
163 : 1 : testData.skip = false;
164 : 1 : suites.get(suiteDesc).push(testData);
165 : 1 :
166 : 1 : // TEST ### - Test addUserScore invalid ... test#6
167 : 1 : testData = {};
168 : 1 :
169 : 1 : testObj = {
170 : 1 : reqMethod: 'POST',
171 : 1 : reqAuth: testUsers[0].token,
172 : 1 : reqBody: {score: 100},
173 : 1 : resCode: 400,
174 : 1 : resBody: 'Submission Error: no activity given',
175 : 1 : };
176 : 1 :
177 : 1 : testData.method = testMethod.bind(testObj);
178 : 1 : testData.desc = 'Test addUserScore invalid ... test#6';
179 : 1 :
180 : 1 : testData.skip = false;
181 : 1 : suites.get(suiteDesc).push(testData);
182 : 1 :
183 : 1 : // TEST ### - Test addUserScore valid ... test#1
184 : 1 : testData = {};
185 : 1 :
186 : 1 : testObj = {
187 : 1 : reqMethod: 'POST',
188 : 1 : reqAuth: testUsers[0].token,
189 : 1 : reqBody: {activity: 'activity-1', score: 100},
190 : 1 : resCode: 201,
191 : 1 : resBody: {activity: 'activity-1', username: testUsers[0].username, score: '100'},
192 : 1 : };
193 : 1 :
194 : 1 : testData.method = testMethod.bind(testObj);
195 : 1 : testData.desc = 'Test addUserScore valid ... test#1';
196 : 1 :
197 : 1 : testData.skip = false;
198 : 1 : suites.get(suiteDesc).push(testData);
199 : 1 :
200 : 1 : // TEST ### - Test addUserScore valid ... test#2
201 : 1 : testData = {};
202 : 1 :
203 : 1 : testObj = {
204 : 1 : reqMethod: 'POST',
205 : 1 : reqAuth: testUsers[0].token,
206 : 1 : reqBody: {activity: 'activity-1', score: 200},
207 : 1 : resCode: 201,
208 : 1 : resBody: {activity: 'activity-1', username: testUsers[0].username, score: '200'},
209 : 1 : };
210 : 1 :
211 : 1 : testData.method = testMethod.bind(testObj);
212 : 1 : testData.desc = 'Test addUserScore valid ... test#2';
213 : 1 :
214 : 1 : testData.skip = false;
215 : 1 : suites.get(suiteDesc).push(testData);
216 : 1 :
217 : 1 : // TEST ### - Test addUserScore valid ... test#3
218 : 1 : testData = {};
219 : 1 :
220 : 1 : testObj = {
221 : 1 : reqMethod: 'POST',
222 : 1 : reqAuth: testUsers[1].token,
223 : 1 : reqBody: {activity: 'activity-1', score: 300},
224 : 1 : resCode: 201,
225 : 1 : resBody: {activity: 'activity-1', username: testUsers[1].username, score: '300'},
226 : 1 : };
227 : 1 :
228 : 1 : testData.method = testMethod.bind(testObj);
229 : 1 : testData.desc = 'Test addUserScore valid ... test#3';
230 : 1 :
231 : 1 : testData.skip = false;
232 : 1 : suites.get(suiteDesc).push(testData);
233 : 1 :
234 : 1 : // TEST SUITE ### - Test Score Route - removeUserScore
235 : 1 : suiteDesc = 'Test Score Route - removeUserScore';
236 : 1 : suites.set(suiteDesc, []);
237 : 1 :
238 : 1 : // TEST ### - Test removeUserScore invalid ... test#1
239 : 1 : testData = {};
240 : 1 :
241 : 1 : testObj = {
242 : 1 : reqMethod: 'PATCH',
243 : 1 : reqAuth: undefined,
244 : 1 : reqBody: undefined,
245 : 1 : resCode: 401,
246 : 1 : resBody: 'Authorization Error: No authorization token was found',
247 : 1 : };
248 : 1 :
249 : 1 : testData.method = testMethod.bind(testObj);
250 : 1 : testData.desc = 'Test removeUserScore invalid ... test#1';
251 : 1 :
252 : 1 : testData.skip = false;
253 : 1 : suites.get(suiteDesc).push(testData);
254 : 1 :
255 : 1 : // TEST ### - Test removeUserScore invalid ... test#2
256 : 1 : testData = {};
257 : 1 :
258 : 1 : testObj = {
259 : 1 : reqMethod: 'PATCH',
260 : 1 : reqAuth: testUsers[0].token,
261 : 1 : reqBody: undefined,
262 : 1 : resCode: 400,
263 : 1 : resBody: 'Submission Error: none or invalid request payload',
264 : 1 : };
265 : 1 :
266 : 1 : testData.method = testMethod.bind(testObj);
267 : 1 : testData.desc = 'Test removeUserScore invalid ... test#2';
268 : 1 :
269 : 1 : testData.skip = false;
270 : 1 : suites.get(suiteDesc).push(testData);
271 : 1 :
272 : 1 : // TEST ### - Test removeUserScore invalid ... test#3
273 : 1 : testData = {};
274 : 1 :
275 : 1 : testObj = {
276 : 1 : reqMethod: 'PATCH',
277 : 1 : reqAuth: testUsers[0].token,
278 : 1 : reqBody: {},
279 : 1 : resCode: 400,
280 : 1 : resBody: 'Submission Error: none or invalid request payload',
281 : 1 : };
282 : 1 :
283 : 1 : testData.method = testMethod.bind(testObj);
284 : 1 : testData.desc = 'Test removeUserScore invalid ... test#3';
285 : 1 :
286 : 1 : testData.skip = false;
287 : 1 : suites.get(suiteDesc).push(testData);
288 : 1 :
289 : 1 : // TEST ### - Test removeUserScore invalid ... test#4
290 : 1 : testData = {};
291 : 1 :
292 : 1 : testObj = {
293 : 1 : reqMethod: 'PATCH',
294 : 1 : reqAuth: testUsers[0].token,
295 : 1 : reqBody: 'XXXXXXX',
296 : 1 : resCode: 400,
297 : 1 : resBody: 'Submission Error: none or invalid request payload',
298 : 1 : };
299 : 1 :
300 : 1 : testData.method = testMethod.bind(testObj);
301 : 1 : testData.desc = 'Test removeUserScore invalid ... test#4';
302 : 1 :
303 : 1 : testData.skip = false;
304 : 1 : suites.get(suiteDesc).push(testData);
305 : 1 :
306 : 1 : // TEST ### - Test removeUserScore invalid ... test#5
307 : 1 : testData = {};
308 : 1 :
309 : 1 : testObj = {
310 : 1 : reqMethod: 'PATCH',
311 : 1 : reqAuth: testUsers[0].token,
312 : 1 : reqBody: {score: 100},
313 : 1 : resCode: 400,
314 : 1 : resBody: 'Submission Error: no activity given',
315 : 1 : };
316 : 1 :
317 : 1 : testData.method = testMethod.bind(testObj);
318 : 1 : testData.desc = 'Test removeUserScore invalid ... test#5';
319 : 1 :
320 : 1 : testData.skip = false;
321 : 1 : suites.get(suiteDesc).push(testData);
322 : 1 :
323 : 1 : // TEST ### - Test removeUserScore valid ... test#1
324 : 1 : testData = {};
325 : 1 :
326 : 1 : testObj = {
327 : 1 : reqMethod: 'PATCH',
328 : 1 : reqAuth: testUsers[1].token,
329 : 1 : reqBody: {activity: 'activity-1'},
330 : 1 : resCode: 204,
331 : 1 : resBody: '',
332 : 1 : };
333 : 1 :
334 : 1 : testData.method = testMethod.bind(testObj);
335 : 1 : testData.desc = 'Test removeUserScore valid ... test#1';
336 : 1 :
337 : 1 : testData.skip = false;
338 : 1 : suites.get(suiteDesc).push(testData);
339 : 1 :
340 : 1 : // TEST SUITE ### - Test Score Route - removeAllUserScores
341 : 1 : suiteDesc = 'Test Score Route - removeAllUserScores';
342 : 1 : suites.set(suiteDesc, []);
343 : 1 :
344 : 1 : // TEST ### - Test removeAllUserScores invalid ... test#1
345 : 1 : testData = {};
346 : 1 :
347 : 1 : testObj = {
348 : 1 : reqMethod: 'POST',
349 : 1 : reqAuth: undefined,
350 : 1 : reqBody: undefined,
351 : 1 : resCode: 401,
352 : 1 : resBody: 'Authorization Error: No authorization token was found',
353 : 1 : };
354 : 1 :
355 : 1 : testData.method = testMethod.bind(testObj);
356 : 1 : testData.desc = 'Test removeAllUserScores invalid ... test#1';
357 : 1 :
358 : 1 : testData.skip = false;
359 : 1 : suites.get(suiteDesc).push(testData);
360 : 1 :
361 : 1 : // TEST ### - Test removeAllUserScores valid ... test#1
362 : 1 : testData = {};
363 : 1 :
364 : 1 : testObj = {
365 : 1 : reqMethod: 'DELETE',
366 : 1 : reqAuth: testUsers[0].token,
367 : 1 : reqBody: undefined,
368 : 1 : resCode: 204,
369 : 1 : resBody: '',
370 : 1 : };
371 : 1 :
372 : 1 : testData.method = testMethod.bind(testObj);
373 : 1 : testData.desc = 'Test removeAllUserScores valid ... test#1';
374 : 1 :
375 : 1 : testData.skip = false;
376 : 1 : suites.get(suiteDesc).push(testData);
377 : 1 :
378 : 1 : // TEST ### - Test removeAllUserScores valid ... test#2
379 : 1 : testData = {};
380 : 1 :
381 : 1 : testObj = {
382 : 1 : reqMethod: 'DELETE',
383 : 1 : reqAuth: testUsers[0].token,
384 : 1 : reqBody: undefined,
385 : 1 : resCode: 204,
386 : 1 : resBody: '',
387 : 1 : };
388 : 1 :
389 : 1 : testData.method = testMethod.bind(testObj);
390 : 1 : testData.desc = 'Test removeAllUserScores valid ... test#2';
391 : 1 :
392 : 1 : testData.skip = false;
393 : 1 : suites.get(suiteDesc).push(testData);
394 : 1 : }
395 : 1 :
396 : 1 : /**
397 : 1 : * @func nodeRunner
398 : 1 : * @param {object} runner - The node core module 'node:test' object.
399 : 1 : * @desc Carry out the loaded tests using node test runner.
400 : 1 : */
401 [ + ]: 1 : function nodeRunner(runner){
402 : 1 :
403 [ + ]: 1 : for(let [suiteDesc, suiteTests] of suites){
404 [ + ]: 3 : runner.suite(suiteDesc, () => {
405 [ + ]: 3 : for(let cmdObj of suiteTests){
406 [ + ]: 18 : runner.test(cmdObj.desc, {skip: cmdObj.skip}, async () => {
407 : 18 : await cmdObj.method();
408 : 18 : });
409 : 18 : }
410 : 3 : });
411 : 3 : }
412 : 1 : }
413 : 1 :
414 : 1 : /**
415 : 1 : * @func
416 : 1 : * @async
417 : 1 : * @desc Carries out the assertions tests.
418 : 1 : */
419 [ + ]: 18 : async function testMethod(){
420 [ + ]: 18 : await new Promise((resolve, reject) => {
421 : 18 :
422 : 18 : let module = http;
423 : 18 : let reqOptions = { method: this.reqMethod };
424 : 18 :
425 : 18 : if(new URL(baseUrl).protocol === 'https:'){
426 : 18 : module = https;
427 : 18 : reqOptions.rejectUnauthorized = false;
428 : 18 : }
429 : 18 :
430 [ + ]: 18 : const cr = module.request(baseUrl, reqOptions, (res) => {
431 : 18 : let body = '';
432 [ + ]: 18 : res.on('data', (chunk) => {
433 : 15 : body += chunk;
434 : 18 : });
435 : 18 :
436 [ + ]: 18 : res.on('end', () => {
437 : 18 : try{
438 : 18 : assert.strictEqual(res.statusCode, this.resCode);
439 : 18 :
440 : 18 : if(this.reqMethod.toUpperCase() !== 'GET'){
441 [ + ]: 18 : if(typeof this.resBody === 'string'){
442 : 15 : assert.strictEqual(body, this.resBody);
443 [ + ]: 15 : }
444 : 3 : else
445 : 3 : if(typeof this.resBody === 'object'){
446 : 3 : assert.deepStrictEqual(
447 [ + ][ + ][ + ]: 3 : JSON.parse(body, (key, value) => key !== 'timestamp' ? value : undefined),
448 : 3 : this.resBody
449 : 3 : );
450 : 3 : }
451 : 18 : }
452 : 18 : resolve();
453 : 18 : }
454 [ - ]: 18 : catch(err){ /* node:coverage disable */
455 : : reject(err);
456 : : } /* node:coverage enable */
457 : 18 : });
458 : 18 : });
459 : 18 :
460 [ + ]: 18 : if(this.reqAuth){
461 : 15 : cr.setHeader('Authorization', `Bearer ${this.reqAuth}`);
462 : 15 : }
463 : 18 :
464 [ + ]: 18 : if(typeof this.reqBody === 'object'){
465 : 9 : this.reqBody = JSON.stringify(this.reqBody);
466 : 9 : cr.setHeader('Content-Type', 'application/json; charset=UTF-8');
467 : 9 : cr.write(this.reqBody);
468 : 9 : }
469 : 9 : else
470 [ + ]: 9 : if(typeof this.reqBody === 'string'){
471 : 2 : cr.setHeader('Content-Type', 'text/plain; charset=UTF-8');
472 : 2 : cr.write(this.reqBody);
473 : 2 : }
474 : 18 : cr.end();
475 : 18 : });
476 : 18 : }
|