@@ -7,15 +7,15 @@ import { SubstituteException } from './SubstituteException'
77import type { FilterFunction , SubstituteContext , SubstitutionMethod , ClearType , PropertyType } from './Types'
88
99const instance = Symbol ( 'Substitute:Instance' )
10- type SpecialProperty = typeof instance | typeof inspect . custom | 'then'
11- type RootContext = { substituteMethodsEnabled : boolean }
12-
1310const clearTypeToFilterMap : Record < ClearType , FilterFunction < SubstituteNode > > = {
1411 all : ( ) => true ,
1512 receivedCalls : node => ! node . hasContext ,
1613 substituteValues : node => node . isSubstitution
1714}
1815
16+ type SpecialProperty = typeof instance | typeof inspect . custom | 'then'
17+ type RootContext = { substituteMethodsEnabled : boolean }
18+
1919export class SubstituteNode extends SubstituteNodeBase {
2020 private _proxy : SubstituteNode
2121 private _rootContext : RootContext
@@ -30,7 +30,7 @@ export class SubstituteNode extends SubstituteNodeBase {
3030 private constructor ( key : PropertyKey , parent ?: SubstituteNode ) {
3131 super ( key , parent )
3232 if ( this . isRoot ( ) ) this . _rootContext = { substituteMethodsEnabled : true }
33- if ( this . isIntermediateNode ( ) ) this . _rootContext = this . root . rootContext
33+ else this . _rootContext = this . root . rootContext
3434 this . _proxy = new Proxy (
3535 this ,
3636 {
@@ -66,11 +66,11 @@ export class SubstituteNode extends SubstituteNodeBase {
6666 return new this ( key , parent )
6767 }
6868
69- public get proxy ( ) {
69+ public get proxy ( ) : SubstituteNode {
7070 return this . _proxy
7171 }
7272
73- public get rootContext ( ) {
73+ public get rootContext ( ) : RootContext {
7474 return this . _rootContext
7575 }
7676
@@ -90,23 +90,23 @@ export class SubstituteNode extends SubstituteNodeBase {
9090 return isAssertionMethod ( this . context )
9191 }
9292
93- get property ( ) {
93+ get property ( ) : PropertyKey {
9494 return this . key
9595 }
9696
97- get propertyType ( ) {
97+ get propertyType ( ) : PropertyType {
9898 return this . _propertyType
9999 }
100100
101101 get accessorType ( ) {
102102 return this . _accessorType
103103 }
104104
105- get recordedArguments ( ) {
105+ get recordedArguments ( ) : RecordedArguments {
106106 return this . _recordedArguments
107107 }
108108
109- public get disabledSubstituteMethods ( ) {
109+ public get disabledSubstituteMethods ( ) : boolean {
110110 return this . _disabledSubstituteMethods
111111 }
112112
@@ -134,22 +134,27 @@ export class SubstituteNode extends SubstituteNodeBase {
134134 }
135135
136136 public clear ( ) {
137+ if ( ! this . recordedArguments . hasArguments ( ) ) throw new TypeError ( 'No args' )
137138 const clearType : ClearType = this . recordedArguments . value [ 0 ] ?? ClearTypeMap . All
138139 const filter = clearTypeToFilterMap [ clearType ]
139140 this . recorder . clearRecords ( filter )
140141 }
141142
142143 public executeSubstitution ( contextArguments : RecordedArguments ) {
144+ if ( ! this . hasChild ( ) ) throw new TypeError ( 'Substitue node has no child' )
145+ if ( ! this . child . recordedArguments . hasArguments ( ) ) throw new TypeError ( 'Child args' )
146+
143147 const substitutionMethod = this . context as SubstitutionMethod
144148 const substitutionValue = this . child . recordedArguments . value . length > 1
145- ? this . child . recordedArguments . value . shift ( )
149+ ? this . child . recordedArguments . value ? .shift ( )
146150 : this . child . recordedArguments . value [ 0 ]
147151 switch ( substitutionMethod ) {
148152 case 'throws' :
149153 throw substitutionValue
150154 case 'mimicks' :
151- const argumentsToApply = this . propertyType === PropertyTypeMap . Property ? [ ] : contextArguments . value
152- return substitutionValue ( ...argumentsToApply )
155+ if ( this . propertyType === PropertyTypeMap . Property ) return substitutionValue ( )
156+ if ( ! contextArguments . hasArguments ( ) ) throw new TypeError ( 'Context arguments cannot be undefined' )
157+ return substitutionValue ( ...contextArguments . value )
153158 case 'resolves' :
154159 return Promise . resolve ( substitutionValue )
155160 case 'rejects' :
@@ -163,6 +168,7 @@ export class SubstituteNode extends SubstituteNodeBase {
163168
164169 public executeAssertion ( ) : void | never {
165170 if ( ! this . isIntermediateNode ( ) ) throw new Error ( 'Not possible' )
171+ if ( ! this . parent . recordedArguments . hasArguments ( ) ) throw new TypeError ( 'Parent args' )
166172 const siblings = [ ...this . getAllSiblings ( ) . filter ( n => ! n . hasContext && n . accessorType === this . accessorType ) ]
167173
168174 const expectedCount = this . parent . recordedArguments . value [ 0 ] ?? undefined
@@ -257,7 +263,7 @@ export class SubstituteNode extends SubstituteNodeBase {
257263 const label = this . isSubstitution
258264 ? '=> '
259265 : this . isAssertion
260- ? `${ this . child . property . toString ( ) } `
266+ ? `${ this . child ? .property . toString ( ) } `
261267 : ''
262268 const s = hasContext
263269 ? ` ${ label } ${ inspect ( this . child ?. recordedArguments , options ) } `
0 commit comments