@@ -38,62 +38,76 @@ export class TaskMockRunner {
3838 public setAnswers ( answers : TaskLibAnswers ) {
3939 this . _answers = answers ;
4040 }
41-
42- checkModuleName ( modName : any ) : boolean {
43- if ( typeof modName !== 'string' ) {
44- return false ;
45- }
46-
41+ /**
42+ * Checks if a module name is valid for import, avoiding local module references.
43+ *
44+ * @param {string } modName - The name of the module to be checked.
45+ * @returns {boolean } Returns true if the module name is valid, otherwise false.
46+ */
47+ checkModuleName ( modName : string ) : boolean {
4748 if ( modName . includes ( '.' ) ) {
48- console . log ( `WARNING : ${ modName } is a local module. Cannot require it from task-lib. Please pass an already imported module .`) ;
49+ console . error ( `ERROR : ${ modName } is a local module. Cannot import it from task-lib. Please pass full path .`) ;
4950 return false ;
5051 }
51-
5252 return true ;
5353 }
5454
55-
55+ /**
56+ * Checks if a method in a new module is mockable based on specified conditions.
57+ *
58+ * @param {object } newModule - The new module containing the method.
59+ * @param {string } methodName - The name of the method to check.
60+ * @param {object } oldModule - The original module from which the method might be inherited.
61+ * @returns {boolean } Returns true if the method is mockable, otherwise false.
62+ */
5663 checkIsMockable ( newModule , methodName , oldModule ) {
64+ // Get the method from the newModule
5765 const method = newModule [ methodName ] ;
5866
67+ // Check if the method exists and is not undefined
5968 if ( ! newModule . hasOwnProperty ( methodName ) || typeof method === 'undefined' ) {
6069 return false ;
6170 }
6271
72+ // Check if the method is a function
6373 if ( typeof method !== 'function' ) {
64- console . log ( `WARNING: ${ methodName } of ${ newModule } is not a function. There is no option to replace getter/setter in this implementation. You can consider changing it.` ) ;
74+ console . warn ( `WARNING: ${ methodName } of ${ newModule } is not a function. There is no option to replace getter/setter in this implementation. You can consider changing it.` ) ;
6575 return false ;
6676 }
6777
78+ // Check if the method is writable
6879 const descriptor = Object . getOwnPropertyDescriptor ( oldModule , methodName ) ;
69-
7080 return descriptor && descriptor . writable !== false ;
7181 }
7282
73-
74-
7583 /**
76- * Register a mock module. When require() is called for the module name,
77- * the mock implementation will be returned instead.
84+ * Registers a mock module, allowing the replacement of methods with mock implementations.
7885 *
79- * @param modName Module name to override .
80- * @param val Mock implementation of the module.
81- * @returns void
86+ * @param { string } modName - The name of the module to be overridden .
87+ * @param { object } modMock - The mock implementation of the module.
88+ * @returns { void }
8289 */
83- public registerMock ( mod : string | object , modMock : object ) : void {
90+ public registerMock ( modName : string , modMock : object ) : void {
8491 this . _moduleCount ++ ;
8592 let oldMod : object ;
8693
94+ // Check if the module name is valid and can be imported
8795 if ( this . checkModuleName ( modName ) ) {
8896 oldMod = require ( modName ) ;
8997 } else {
90- oldMod = modName ;
98+ console . error ( `ERROR: Cannot import ${ modName } .` ) ;
99+ return ;
91100 }
92101
102+ // Iterate through methods in the old module and replace them with mock implementations
93103 for ( let method in oldMod ) {
94- if ( this . checkIsMockable ( mod , method , oldMod ) ) {
95- const replacement = mod [ method ] || oldMod [ method ] ;
96- this . _sandbox . replace ( oldMod , method , replacement ) ;
104+ if ( this . checkIsMockable ( modMock , method , oldMod ) ) {
105+ const replacement = modMock [ method ] || oldMod [ method ] ;
106+ try {
107+ this . _sandbox . replace ( oldMod , method , replacement ) ;
108+ } catch ( error ) {
109+ console . error ( 'ERROR: Cannot replace ${method} in ${oldMod} by ${replacement}. ${error.message}' , ) ;
110+ }
97111 }
98112 }
99113 }
@@ -126,7 +140,7 @@ export class TaskMockRunner {
126140 }
127141 // register mock task lib
128142 else {
129- var tlm = require ( 'azure-pipelines-task-lib/mock-task' ) ;
143+ let tlm = require ( 'azure-pipelines-task-lib/mock-task' ) ;
130144 if ( this . _answers ) {
131145 tlm . setAnswers ( this . _answers ) ;
132146 }
@@ -136,8 +150,8 @@ export class TaskMockRunner {
136150 tlm [ key ] = this . _exports [ key ] ;
137151 } ) ;
138152
139-
140- var tlt = require ( 'azure-pipelines-task-lib/task' ) ;
153+ // With sinon we have to iterate through methods in the old module and replace them with mock implementations
154+ let tlt = require ( 'azure-pipelines-task-lib/task' ) ;
141155 for ( let method in tlt ) {
142156 if ( tlm . hasOwnProperty ( method ) ) {
143157 this . _sandbox . replace ( tlt , method , tlm [ method ] ) ;
@@ -149,7 +163,11 @@ export class TaskMockRunner {
149163 // run it
150164 require ( this . _taskPath ) ;
151165 }
152-
166+ /**
167+ * Restores the sandboxed environment to its original state.
168+ *
169+ * @returns {void }
170+ */
153171 public restore ( ) {
154172 this . _sandbox . restore ( ) ;
155173 }
0 commit comments