@@ -38,62 +38,76 @@ export class TaskMockRunner {
38
38
public setAnswers ( answers : TaskLibAnswers ) {
39
39
this . _answers = answers ;
40
40
}
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 {
47
48
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 .`) ;
49
50
return false ;
50
51
}
51
-
52
52
return true ;
53
53
}
54
54
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
+ */
56
63
checkIsMockable ( newModule , methodName , oldModule ) {
64
+ // Get the method from the newModule
57
65
const method = newModule [ methodName ] ;
58
66
67
+ // Check if the method exists and is not undefined
59
68
if ( ! newModule . hasOwnProperty ( methodName ) || typeof method === 'undefined' ) {
60
69
return false ;
61
70
}
62
71
72
+ // Check if the method is a function
63
73
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.` ) ;
65
75
return false ;
66
76
}
67
77
78
+ // Check if the method is writable
68
79
const descriptor = Object . getOwnPropertyDescriptor ( oldModule , methodName ) ;
69
-
70
80
return descriptor && descriptor . writable !== false ;
71
81
}
72
82
73
-
74
-
75
83
/**
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.
78
85
*
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 }
82
89
*/
83
- public registerMock ( mod : string | object , modMock : object ) : void {
90
+ public registerMock ( modName : string , modMock : object ) : void {
84
91
this . _moduleCount ++ ;
85
92
let oldMod : object ;
86
93
94
+ // Check if the module name is valid and can be imported
87
95
if ( this . checkModuleName ( modName ) ) {
88
96
oldMod = require ( modName ) ;
89
97
} else {
90
- oldMod = modName ;
98
+ console . error ( `ERROR: Cannot import ${ modName } .` ) ;
99
+ return ;
91
100
}
92
101
102
+ // Iterate through methods in the old module and replace them with mock implementations
93
103
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
+ }
97
111
}
98
112
}
99
113
}
@@ -126,7 +140,7 @@ export class TaskMockRunner {
126
140
}
127
141
// register mock task lib
128
142
else {
129
- var tlm = require ( 'azure-pipelines-task-lib/mock-task' ) ;
143
+ let tlm = require ( 'azure-pipelines-task-lib/mock-task' ) ;
130
144
if ( this . _answers ) {
131
145
tlm . setAnswers ( this . _answers ) ;
132
146
}
@@ -136,8 +150,8 @@ export class TaskMockRunner {
136
150
tlm [ key ] = this . _exports [ key ] ;
137
151
} ) ;
138
152
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' ) ;
141
155
for ( let method in tlt ) {
142
156
if ( tlm . hasOwnProperty ( method ) ) {
143
157
this . _sandbox . replace ( tlt , method , tlm [ method ] ) ;
@@ -149,7 +163,11 @@ export class TaskMockRunner {
149
163
// run it
150
164
require ( this . _taskPath ) ;
151
165
}
152
-
166
+ /**
167
+ * Restores the sandboxed environment to its original state.
168
+ *
169
+ * @returns {void }
170
+ */
153
171
public restore ( ) {
154
172
this . _sandbox . restore ( ) ;
155
173
}
0 commit comments