LCOV - code coverage report
Current view: top level - test - utils.test.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 185 185 100.0 %
Date: 2025-03-25 04:04:09 Functions: 8 10 80.0 %
Branches: 14 17 82.4 %

           Branch data     Line data    Source code
       1            [ + ]:          1 : /**
       2                 :          1 :  * @module  utilities-test
       3                 :          1 :  * @desc        Testing module for the {@link module:utilities utilities} 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 : 
      11                 :          1 : /* Import the tested module */
      12                 :          1 : import {updateObject, isValidObject, extractSubobjectByKeys} from '../lib/utils.js';
      13                 :          1 : 
      14                 :          1 : /* Prepare test environment */
      15                 :          1 : let testCount   = 1;
      16                 :          1 : let passCount   = 0;
      17                 :          1 : let failCount   = 0;
      18                 :          1 : let cancelCount = 0;
      19                 :          1 : let skipCount   = 0;
      20                 :          1 : let todoCount   = 0;
      21                 :          1 : let startTime   = Date.now();
      22                 :          1 : 
      23                 :          1 : const suites = new Map();
      24                 :          1 : 
      25                 :          1 : /** @const {object} cmdOptions - Testing options. */
      26                 :          1 : const cmdOptions = {
      27                 :          1 :         node    : true,
      28                 :          1 :     verbose : true,
      29                 :          1 : };
      30                 :          1 : 
      31                 :          1 : /**
      32                 :          1 :  * @func Main
      33                 :          1 :  * @desc The application entry point function.
      34                 :          1 :  */
      35            [ + ]:          1 : (() => {
      36                 :          1 :         loadTestData();
      37                 :          1 : 
      38                 :          1 :         if(cmdOptions.node){
      39                 :          1 : 
      40                 :          1 :                 import('node:test')
      41            [ + ]:          1 :                         .then(runner => {
      42                 :          1 :                                 cmdOptions.verbose = false;
      43                 :          1 :                                 nodeRunner(runner);
      44                 :          1 :                         })      /* node:coverage disable */
      45                 :            :                         .catch((e) => {
      46                 :            :                                 defRunner();
      47                 :            :                         });
      48            [ - ]:            :         }
      49                 :            :         else{
      50                 :            :                 defRunner();
      51                 :            :         }       /* node:coverage enable */
      52                 :          1 : })('Main Function');
      53                 :          1 : 
      54                 :          1 : /**
      55                 :          1 :  * @func loadTestData
      56                 :          1 :  * @desc Load test data.
      57                 :          1 :  */
      58            [ + ]:          1 : function loadTestData(){
      59                 :          1 : 
      60                 :          1 :         let testData = null;
      61                 :          1 :         let suiteDesc = '';
      62                 :          1 : 
      63                 :          1 :         // TEST SUITE #1 - Test utilities functions
      64                 :          1 :         suiteDesc = 'Test utilities functions';
      65                 :          1 :         suites.set(suiteDesc, []);
      66                 :          1 : 
      67                 :          1 :         // TEST ### - Function updateObject()...test#1
      68                 :          1 :         testData = {};
      69                 :          1 : 
      70            [ + ]:          1 :         testData.method = async () => {
      71                 :          1 : 
      72                 :          1 :                 const originalDict = { name: 'Alice', age: 30, location: 'New York', email: 'alice@example.com' };
      73                 :          1 :                 const updatesDict  = { name: 'Alice Smith', age: 31, location: 'Los Angeles', email: 'alice.smith@example.com' };
      74                 :          1 : 
      75                 :          1 :                 const keysToExclude = ['email'];
      76                 :          1 :                 const expectDict = { name: 'Alice Smith', age: 31, location: 'Los Angeles', email: 'alice@example.com' };
      77                 :          1 : 
      78                 :          1 :                 updateObject(originalDict, updatesDict, keysToExclude);
      79                 :          1 :                 assert.deepStrictEqual(originalDict, expectDict);
      80                 :          1 :         };
      81                 :          1 :         testData.desc = 'Function updateObject()...test#1';
      82                 :          1 : 
      83                 :          1 :         testData.skip = false;
      84                 :          1 :         suites.get(suiteDesc).push(testData);
      85                 :          1 : 
      86                 :          1 :         // TEST ### - Function isValidObject()...test#1
      87                 :          1 :         testData = {};
      88                 :          1 : 
      89            [ + ]:          1 :         testData.method = async () => {
      90                 :          1 : 
      91                 :          1 :                 const validDict = { name: 'Alice', age: 30 };
      92                 :          1 :                 const allowedKeys = ['name', 'age', 'email'];
      93                 :          1 : 
      94                 :          1 :                 assert(isValidObject(validDict, allowedKeys));
      95                 :          1 :         };
      96                 :          1 :         testData.desc = 'Function isValidObject()...test#1';
      97                 :          1 : 
      98                 :          1 :         testData.skip = false;
      99                 :          1 :         suites.get(suiteDesc).push(testData);
     100                 :          1 : 
     101                 :          1 :         // TEST ### - Function isValidObject()...test#2
     102                 :          1 :         testData = {};
     103                 :          1 : 
     104            [ + ]:          1 :         testData.method = async () => {
     105                 :          1 : 
     106                 :          1 :                 const invalidDict = { name: 'Bob', age: 25, location: 'City' };
     107                 :          1 :                 const allowedKeys = ['name', 'age', 'email'];
     108                 :          1 : 
     109                 :          1 :                 assert(!isValidObject(invalidDict, allowedKeys));
     110                 :          1 :         };
     111                 :          1 :         testData.desc = 'Function isValidObject()...test#2';
     112                 :          1 : 
     113                 :          1 :         testData.skip = false;
     114                 :          1 :         suites.get(suiteDesc).push(testData);
     115                 :          1 : 
     116                 :          1 :         // TEST ### - Function isValidObject()...test#3
     117                 :          1 :         testData = {};
     118                 :          1 : 
     119            [ + ]:          1 :         testData.method = async () => {
     120                 :          1 : 
     121                 :          1 :                 const notDict = ['name', 'Alice'];
     122                 :          1 :                 const allowedKeys = ['name', 'age', 'email'];
     123                 :          1 : 
     124                 :          1 :                 assert(!isValidObject(notDict, allowedKeys));
     125                 :          1 :         };
     126                 :          1 :         testData.desc = 'Function isValidObject()...test#3';
     127                 :          1 : 
     128                 :          1 :         testData.skip = false;
     129                 :          1 :         suites.get(suiteDesc).push(testData);
     130                 :          1 : 
     131                 :          1 :         // TEST ### - Function extractSubobjectByKeys()...test#1
     132                 :          1 :         testData = {};
     133                 :          1 : 
     134            [ + ]:          1 :         testData.method = async () => {
     135                 :          1 : 
     136                 :          1 :                 const originalDict = {
     137                 :          1 :                         name: 'John Doe',
     138                 :          1 :                         age: 30,
     139                 :          1 :                         email: 'johndoe@example.com',
     140                 :          1 :                         country: 'USA'
     141                 :          1 :                 };
     142                 :          1 :                 const keysList = ['name', 'email'];
     143                 :          1 : 
     144                 :          1 :                 const subDict = extractSubobjectByKeys(originalDict, keysList);
     145                 :          1 : 
     146                 :          1 :                 assert.deepStrictEqual(subDict, { name: 'John Doe', email: 'johndoe@example.com' });
     147                 :          1 :         };
     148                 :          1 :         testData.desc = 'Function extractSubobjectByKeys()...test#1';
     149                 :          1 : 
     150                 :          1 :         testData.skip = false;
     151                 :          1 :         suites.get(suiteDesc).push(testData);
     152                 :          1 : }
     153                 :          1 : 
     154                 :          1 : /**
     155                 :          1 :  * @func  nodeRunner
     156                 :          1 :  * @param {object} runner - The node core module 'node:test' object.
     157                 :          1 :  * @desc  Carry out the loaded tests using node test runner.
     158                 :          1 :  */
     159            [ + ]:          1 : function nodeRunner(runner){
     160                 :          1 : 
     161                 :          1 :         for(let [suiteDesc, suiteTests] of suites){
     162            [ + ]:          1 :                 runner.suite(suiteDesc, () => {
     163            [ + ]:          1 :                         for(let cmdObj of suiteTests){
     164            [ + ]:          5 :                                 runner.test(cmdObj.desc, {skip: cmdObj.skip}, async () => {
     165                 :          5 :                                         await makeTest(cmdObj);
     166                 :          5 :                                 });
     167                 :          5 :                         }
     168                 :          1 :                 });
     169                 :          1 :         }
     170                 :          1 : }
     171                 :          1 : /* node:coverage disable */
     172                 :            : 
     173                 :            : /**
     174                 :            :  * @func  defRunner
     175                 :            :  * @desc  Carry out the loaded tests using this developed test runner.
     176                 :            :  */
     177                 :            : function defRunner(){
     178                 :            : 
     179                 :            :         cmdOptions.verbose && process.on('exit', () => {
     180                 :            :                 console.log();
     181                 :            :                 console.log('▶ tests',       --testCount);
     182                 :            :                 console.log('▶ suites',      suites.size);
     183                 :            :                 console.log('▶ pass',        passCount);
     184                 :            :                 console.log('▶ fail',        failCount);
     185                 :            :                 console.log('▶ cancelled',   cancelCount);
     186                 :            :                 console.log('▶ skipped',     skipCount);
     187                 :            :                 console.log('▶ todo',        todoCount);
     188                 :            :                 console.log('▶ duration_ms', Math.round(Date.now() - startTime));
     189                 :            :         });
     190                 :            : 
     191                 :            :         cmdOptions.verbose && console.error();
     192                 :            :         for(let [suiteDesc, suiteTests] of suites)
     193                 :            :                 for(let cmdObj of suiteTests)
     194                 :            :                         if(!cmdObj.skip){
     195                 :            :                                 (async() => {
     196                 :            :                                         await makeTest(cmdObj);
     197                 :            :                                 })();
     198                 :            :                         }
     199                 :            : 
     200                 :            :         cmdOptions.verbose && console.log();
     201                 :            : }
     202                 :            : /* node:coverage enable */
     203                 :          1 : 
     204                 :          1 : /**
     205                 :          1 :  * @func  makeTest
     206                 :          1 :  * async
     207                 :          1 :  * @param {object} obj - The test data object.
     208                 :          1 :  * @desc  Carry out a single test.
     209                 :          1 :  */
     210            [ + ]:          5 : async function makeTest(obj){
     211                 :          5 : 
     212                 :          5 :         const testID   = testCount++;
     213                 :          5 : 
     214                 :          5 :         let preMsg = `Test#${(testID).toString().padStart(3, '0')} ... `;
     215                 :          5 :         let postMsg = preMsg;
     216                 :          5 : 
     217                 :          5 :         preMsg += `Initiate ... ${obj.desc}`;
     218            [ - ]:          5 :         cmdOptions.verbose && console.error(preMsg);
     219                 :          5 : 
     220                 :          5 :         if(!cmdOptions.verbose){
     221                 :          5 :                 await obj.method();
     222            [ - ]:          5 :         }       /* node:coverage disable */
     223                 :            :         else{
     224                 :            :                 try{
     225                 :            :                         await obj.method();
     226                 :            :                         passCount++;
     227                 :            : 
     228                 :            :                         postMsg += `Success  ... ${obj.desc}`;
     229                 :            :                         cmdOptions.verbose && console.error(postMsg);
     230                 :            :                 }
     231                 :            :                 catch(e){
     232                 :            :                         failCount++;
     233                 :            : 
     234                 :            :                         postMsg += `Failure  ... ${obj.desc}`;
     235                 :            :                         cmdOptions.verbose && console.error(postMsg);
     236                 :            :                 }
     237                 :            :         }       /* node:coverage enable */
     238                 :          5 : }

Generated by: LCOV version 1.14