@@ -4,16 +4,11 @@ import { SubstituteNodeBase } from './SubstituteNodeBase'
44import { RecordedArguments } from './RecordedArguments'
55import { ClearType as ClearTypeMap , PropertyType as PropertyTypeMap , isAssertionMethod , isSubstituteMethod , isSubstitutionMethod , textModifier , isConfigurationMethod } from './Utilities'
66import { SubstituteException } from './SubstituteException'
7- import type { FilterFunction , SubstituteContext , SubstitutionMethod , ClearType , PropertyType } from './Types'
7+ import type { FilterFunction , SubstituteContext , SubstitutionMethod , PropertyType } from './Types'
88import type { ObjectSubstitute } from './Transformations'
9- import { didNotReceive , mimick , mimicks , received , rejects , resolves , returns , throws } from './Symbols '
9+ import { didNotReceive , mimick , mimicks , received , rejects , resolves , returns , throws , clearReceivedCalls } from './Transformations '
1010
1111const instance = Symbol ( 'Substitute:Instance' )
12- const clearTypeToFilterMap : Record < ClearType , FilterFunction < SubstituteNode > > = {
13- all : ( ) => true ,
14- receivedCalls : node => ! node . hasContext ,
15- substituteValues : node => node . isSubstitution
16- }
1712
1813type SpecialProperty = typeof instance | typeof inspect . custom | 'then'
1914type RootContext = { substituteMethodsEnabled : boolean }
@@ -31,35 +26,54 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu
3126
3227 private constructor ( key : PropertyKey , parent ?: SubstituteNode ) {
3328 super ( key , parent )
34- if ( this . isRoot ( ) ) this . _rootContext = { substituteMethodsEnabled : true }
35- else this . _rootContext = this . root . rootContext
29+ if ( this . isRoot ( ) ) {
30+ this . _rootContext = { substituteMethodsEnabled : true }
31+ }
32+ else {
33+ this . _rootContext = this . root . rootContext
34+ }
35+
3636 this . _proxy = new Proxy (
3737 this ,
3838 {
3939 get : function ( target , property ) {
40- if ( target . isSpecialProperty ( property ) ) return target . evaluateSpecialProperty ( property )
41- if ( target . _retrySubstitutionExecutionAttempt ) return target . reattemptSubstitutionExecution ( ) [ property ]
40+ if ( target . isSpecialProperty ( property ) )
41+ return target . evaluateSpecialProperty ( property )
42+
43+ if ( target . _retrySubstitutionExecutionAttempt )
44+ return target . reattemptSubstitutionExecution ( ) [ property ]
45+
4246 const newNode = SubstituteNode . createChild ( property , target )
43- if ( target . isAssertion ) newNode . executeAssertion ( )
47+ if ( target . isAssertion )
48+ newNode . executeAssertion ( )
49+
4450 if ( target . isRoot ( ) && target . rootContext . substituteMethodsEnabled && ( isAssertionMethod ( property ) || isConfigurationMethod ( property ) ) ) {
4551 newNode . assignContext ( property )
4652 return newNode [ property ] . bind ( newNode )
4753 }
54+
4855 return newNode . attemptSubstitutionExecution ( )
4956 } ,
5057 set : function ( target , property , value ) {
5158 const newNode = SubstituteNode . createChild ( property , target )
5259 newNode . handleSetter ( value )
53- if ( target . isAssertion ) newNode . executeAssertion ( )
60+ if ( target . isAssertion )
61+ newNode . executeAssertion ( )
62+
5463 return true
5564 } ,
5665 apply : function ( target , _thisArg , rawArguments ) {
5766 target . handleMethod ( rawArguments )
5867 if ( target . hasDepthOfAtLeast ( 2 ) ) {
59- if ( isSubstitutionMethod ( target . property ) ) return target . parent . assignContext ( target . property )
60- if ( target . parent . isAssertion ) return target . executeAssertion ( )
68+ if ( isSubstitutionMethod ( target . property ) )
69+ return target . parent . assignContext ( target . property )
70+
71+ if ( target . parent . isAssertion )
72+ return target . executeAssertion ( )
6173 }
62- return target . isAssertion ? target . proxy : target . attemptSubstitutionExecution ( )
74+ return target . isAssertion ?
75+ target . proxy :
76+ target . attemptSubstitutionExecution ( )
6377 }
6478 }
6579 )
@@ -129,9 +143,10 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu
129143 throw new Error ( 'Mimick is not implemented yet' )
130144 }
131145
132- public clearSubstitute ( clearType : ClearType = ClearTypeMap . All ) : void {
133- this . handleMethod ( [ clearType ] )
134- const filter = clearTypeToFilterMap [ clearType ]
146+ public [ clearReceivedCalls ] ( ) : void {
147+ this . handleMethod ( [ ] )
148+
149+ const filter = ( node : SubstituteNode ) => ! node . hasContext
135150 this . recorder . clearRecords ( filter )
136151 }
137152
@@ -140,7 +155,9 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu
140155 }
141156
142157 private assignContext ( context : SubstituteContext ) : void {
143- if ( ! isSubstituteMethod ( context ) ) throw new Error ( `Cannot assign context for property ${ context . toString ( ) } ` )
158+ if ( ! isSubstituteMethod ( context ) )
159+ throw new Error ( `Cannot assign context for property ${ context . toString ( ) } ` )
160+
144161 this . _context = context
145162 }
146163
@@ -158,8 +175,11 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu
158175 }
159176
160177 private executeSubstitution ( contextArguments : RecordedArguments ) {
161- if ( ! this . hasChild ( ) ) throw new TypeError ( 'Substitue node has no child' )
162- if ( ! this . child . recordedArguments . hasArguments ( ) ) throw new TypeError ( 'Child args' )
178+ if ( ! this . hasChild ( ) )
179+ throw new TypeError ( 'Substitue node has no child' )
180+
181+ if ( ! this . child . recordedArguments . hasArguments ( ) )
182+ throw new TypeError ( 'Child args' )
163183
164184 const substitutionMethod = this . context as SubstitutionMethod
165185 const substitutionValue = this . child . recordedArguments . value . length > 1
@@ -168,10 +188,16 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu
168188 switch ( substitutionMethod ) {
169189 case throws :
170190 throw substitutionValue
191+
171192 case mimicks :
172- if ( this . propertyType === PropertyTypeMap . Property ) return substitutionValue ( )
173- if ( ! contextArguments . hasArguments ( ) ) throw new TypeError ( 'Context arguments cannot be undefined' )
193+ if ( this . propertyType === PropertyTypeMap . Property )
194+ return substitutionValue ( )
195+
196+ if ( ! contextArguments . hasArguments ( ) )
197+ throw new TypeError ( 'Context arguments cannot be undefined' )
198+
174199 return substitutionValue ( ...contextArguments . value )
200+
175201 case resolves :
176202 return Promise . resolve ( substitutionValue )
177203 case rejects :
@@ -184,8 +210,12 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu
184210 }
185211
186212 private executeAssertion ( ) : void | never {
187- if ( ! this . hasDepthOfAtLeast ( 2 ) ) throw new Error ( 'Not possible' )
188- if ( ! this . parent . recordedArguments . hasArguments ( ) ) throw new TypeError ( 'Parent args' )
213+ if ( ! this . hasDepthOfAtLeast ( 2 ) )
214+ throw new Error ( 'Not possible' )
215+
216+ if ( ! this . parent . recordedArguments . hasArguments ( ) )
217+ throw new TypeError ( 'Parent args' )
218+
189219 const expectedCount = this . parent . recordedArguments . value [ 0 ] ?? undefined
190220 const finiteExpectation = expectedCount !== undefined
191221 if ( finiteExpectation && ( ! Number . isInteger ( expectedCount ) || expectedCount < 0 ) ) throw new Error ( 'Expected count has to be a positive integer' )
0 commit comments