@@ -10,187 +10,203 @@ import { noop, stringify } from '@polkadot/util';
1010
1111import { ScProvider } from './index.js' ;
1212
13- interface MockChain extends Sc . Chain {
14- _spec : ( ) => string ;
15- _recevedRequests : ( ) => string [ ] ;
13+ // Well known chain constants
14+ const mockWellKnownChain = {
15+ polkadot : 'polkadot' ,
16+ ksmcc3 : 'ksmcc3' ,
17+ rococo_v2_2 : 'rococo_v2_2' ,
18+ westend2 : 'westend2' ,
19+ paseo : 'paseo'
20+ } as const ;
21+
22+ interface MockChain {
23+ sendJsonRpc : ( rpc : string ) => void ;
24+ remove : ( ) => void ;
25+ nextJsonRpcResponse : ( ) => Promise < string > ;
26+ jsonRpcResponses : AsyncIterableIterator < string > ;
27+ addChain : Sc . AddChain ;
28+ _requests : string [ ] ;
29+ _terminated : boolean ;
30+ _callback : ( response : string ) => void ;
31+ _interceptor : ( ( rpc : string ) => void ) | null ;
32+ _setInterceptor : ( fn : ( ( rpc : string ) => void ) | null ) => void ;
33+ _getLatestRequest : ( ) => string | undefined ;
34+ _triggerCallback : ( response : unknown ) => void ;
1635 _isTerminated : ( ) => boolean ;
17- _triggerCallback : ( response : string | object ) => void ;
18- _setTerminateInterceptor : ( fn : ( ) => void ) => void ;
19- _setSendJsonRpcInterceptor : ( fn : ( rpc : string ) => void ) => void ;
20- _getLatestRequest : ( ) => string ;
21- }
22-
23- interface MockedHealthChecker extends HealthChecker {
24- _isActive : ( ) => boolean ;
25- _triggerHealthUpdate : ( update : SmoldotHealth ) => void ;
26- }
27-
28- type MockSc = typeof Sc & {
29- latestChain : ( ) => MockChain ;
30- } ;
31-
32- enum WellKnownChain {
33- polkadot = 'polkadot' ,
34- ksmcc3 = 'ksmcc3' ,
35- rococo_v2_2 = 'rococo_v2_2' ,
36- westend2 = 'westend2'
36+ _setSendJsonRpcInterceptor : ( fn : ( ( rpc : string ) => void ) | null ) => void ;
37+ _recevedRequests : ( ) => string [ ] ;
3738}
3839
39- const wait = ( ms : number ) =>
40- new Promise ( ( resolve ) =>
41- setTimeout ( resolve , ms )
42- ) ;
43-
44- function healthCheckerMock ( ) : MockedHealthChecker {
45- let cb : ( health : SmoldotHealth ) => void = ( ) => undefined ;
46- let sendJsonRpc : ( request : string ) => void = ( ) => undefined ;
47- let isActive = false ;
40+ // Helper function to wait for a specified number of milliseconds
41+ const wait = ( ms : number ) : Promise < void > => new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
42+
43+ function createMockChain ( callback : ( response : string ) => void ) : MockChain {
44+ const requests : string [ ] = [ ] ;
45+ let terminated = false ;
46+ let interceptor : ( ( rpc : string ) => void ) | null = null ;
47+ let responseQueue : string [ ] = [ ] ;
48+
49+ const nextJsonRpcResponse : MockChain [ 'nextJsonRpcResponse' ] = async ( ) => {
50+ if ( responseQueue . length === 0 ) {
51+ return new Promise < string > ( ( resolve ) => {
52+ const checkQueue = ( ) => {
53+ if ( responseQueue . length > 0 ) {
54+ resolve ( responseQueue . shift ( ) ! ) ;
55+ } else {
56+ setTimeout ( checkQueue , 10 ) ;
57+ }
58+ } ;
59+ checkQueue ( ) ;
60+ } ) ;
61+ }
62+ return responseQueue . shift ( ) ! ;
63+ }
4864
49- return {
50- _isActive : ( ) => isActive ,
51- _triggerHealthUpdate : ( update : SmoldotHealth ) => {
52- cb ( update ) ;
65+ const jsonRpcResponses : MockChain [ 'jsonRpcResponses' ] = {
66+ async next ( ) {
67+ const value = await nextJsonRpcResponse ( ) ;
68+ return { done : false , value } ;
5369 } ,
54- responsePassThrough : ( response ) => response ,
55- sendJsonRpc : ( ...args ) => sendJsonRpc ( ...args ) ,
56- setSendJsonRpc : ( cb ) => {
57- sendJsonRpc = cb ;
70+ [ Symbol . asyncIterator ] ( ) {
71+ return this ;
5872 } ,
59- start : ( x ) => {
60- isActive = true ;
61- cb = x ;
73+ return : ( ) => Promise . resolve ( { done : true , value : undefined } ) ,
74+ throw : ( ) => Promise . resolve ( { done : true , value : undefined } )
75+ }
76+
77+ const chain : MockChain = {
78+ _requests : requests ,
79+ _terminated : terminated ,
80+ _callback : ( response : string ) => {
81+ responseQueue . push ( response ) ;
82+ callback ( response ) ;
6283 } ,
63- stop : ( ) => {
64- isActive = false ;
65- }
66- } ;
67- }
68-
69- function healthCheckerFactory ( ) {
70- const _healthCheckers : MockedHealthChecker [ ] = [ ] ;
71-
72- return {
73- _healthCheckers,
74- _latestHealthChecker : ( ) => _healthCheckers . slice ( - 1 ) [ 0 ] ,
75- healthChecker : ( ) => {
76- const result = healthCheckerMock ( ) ;
77-
78- _healthCheckers . push ( result ) ;
79-
80- return result ;
81- }
82- } ;
83- }
84-
85- function getFakeChain ( spec : string , callback : Sc . JsonRpcCallback ) : MockChain {
86- const _receivedRequests : string [ ] = [ ] ;
87- let _isTerminated = false ;
84+ _interceptor : null ,
85+ _setInterceptor : ( fn : ( ( rpc : string ) => void ) | null ) => {
86+ interceptor = fn ;
87+ } ,
88+ _getLatestRequest : ( ) => requests [ requests . length - 1 ] ,
89+ sendJsonRpc : ( rpc : string ) => {
90+ if ( terminated ) {
91+ throw new Error ( 'Chain terminated' ) ;
92+ }
8893
89- let terminateInterceptor = Function . prototype ;
90- let sendJsonRpcInterceptor = Function . prototype ;
94+ if ( interceptor ) {
95+ interceptor ( rpc ) ;
96+ }
9197
92- return {
93- _getLatestRequest : ( ) => _receivedRequests [ _receivedRequests . length - 1 ] ,
94- _isTerminated : ( ) => _isTerminated ,
95- _recevedRequests : ( ) => _receivedRequests ,
96- _setSendJsonRpcInterceptor : ( fn ) => {
97- sendJsonRpcInterceptor = fn ;
98+ requests . push ( rpc ) ;
9899 } ,
99- _setTerminateInterceptor : ( fn ) => {
100- terminateInterceptor = fn ;
100+ remove : ( ) => {
101+ terminated = true ;
101102 } ,
102- _spec : ( ) => spec ,
103- _triggerCallback : ( response ) => {
104- callback (
105- typeof response === 'string'
106- ? response
107- : stringify ( response )
108- ) ;
103+ nextJsonRpcResponse,
104+ jsonRpcResponses,
105+ addChain : async ( ) => createMockChain ( noop ) ,
106+ _triggerCallback : ( response : unknown ) => {
107+ callback ( stringify ( response ) ) ;
109108 } ,
110- addChain : ( chainSpec , jsonRpcCallback ) =>
111- Promise . resolve ( getFakeChain ( chainSpec , jsonRpcCallback ?? noop ) ) ,
112- remove : ( ) => {
113- terminateInterceptor ( ) ;
114- _isTerminated = true ;
109+ _isTerminated : ( ) => terminated ,
110+ _setSendJsonRpcInterceptor : ( fn : ( ( rpc : string ) => void ) | null ) => {
111+ interceptor = fn ;
115112 } ,
116- sendJsonRpc : ( rpc ) => {
117- sendJsonRpcInterceptor ( rpc ) ;
118- _receivedRequests . push ( rpc ) ;
119- }
113+ _recevedRequests : ( ) => requests
120114 } ;
115+
116+ return chain ;
121117}
122118
123- function getFakeClient ( ) {
119+ function createMockClient ( ) {
124120 const chains : MockChain [ ] = [ ] ;
125- let addChainInterceptor : Promise < void > = Promise . resolve ( ) ;
126- let addWellKnownChainInterceptor : Promise < void > = Promise . resolve ( ) ;
121+ let interceptor : Promise < void > = Promise . resolve ( ) ;
127122
128123 return {
129- _chains : ( ) => chains ,
130- _setAddChainInterceptor : ( interceptor : Promise < void > ) => {
131- addChainInterceptor = interceptor ;
132- } ,
133- _setAddWellKnownChainInterceptor : ( interceptor : Promise < void > ) => {
134- addWellKnownChainInterceptor = interceptor ;
135- } ,
136- addChain : ( chainSpec : string , cb : Sc . JsonRpcCallback ) : Promise < MockChain > =>
137- addChainInterceptor . then ( ( ) => {
138- const result = getFakeChain ( chainSpec , cb ) ;
124+ addChain : async ( spec : string ) => {
125+ await interceptor ;
126+ const chain = createMockChain ( noop ) ;
139127
140- chains . push ( result ) ;
128+ chains . push ( chain ) ;
141129
142- return result ;
143- } ) ,
144- addWellKnownChain : (
145- wellKnownChain : string ,
146- cb : Sc . JsonRpcCallback
147- ) : Promise < MockChain > =>
148- addWellKnownChainInterceptor . then ( ( ) => {
149- const result = getFakeChain ( wellKnownChain , cb ) ;
130+ return chain ;
131+ } ,
132+ addWellKnownChain : async ( chain : string ) => {
133+ await interceptor ;
134+ const mockChain = createMockChain ( noop ) ;
150135
151- chains . push ( result ) ;
136+ chains . push ( mockChain ) ;
152137
153- return result ;
154- } )
138+ return mockChain ;
139+ } ,
140+ _chains : chains ,
141+ _setInterceptor : ( p : Promise < void > ) => {
142+ interceptor = p ;
143+ } ,
144+ latestChain : ( ) => chains [ chains . length - 1 ]
155145 } ;
156146}
157147
158- function connectorFactory ( ) : MockSc {
159- const clients : ReturnType < typeof getFakeClient > [ ] = [ ] ;
160- const latestClient = ( ) => clients [ clients . length - 1 ] ;
161-
162- return {
163- WellKnownChain,
164- _clients : ( ) => clients ,
165- createScClient : ( ) => {
166- const result = getFakeClient ( ) ;
167-
168- clients . push ( result ) ;
148+ // Mock client instance that will be shared
149+ let mockClient = createMockClient ( ) ;
150+
151+ // Mock Sc client with mockClient instance
152+ const mockSc = {
153+ createScClient : ( ) => {
154+ mockClient = createMockClient ( ) ;
155+ return mockClient ;
156+ } ,
157+ WellKnownChain : mockWellKnownChain ,
158+ latestChain : ( ) => mockClient . latestChain ( )
159+ } ;
169160
170- return result ;
171- } ,
172- latestChain : ( ) =>
173- latestClient ( ) . _chains ( ) [ latestClient ( ) . _chains ( ) . length - 1 ] ,
174- latestClient
175- } as unknown as MockSc ;
176- }
161+ // Mock health checker factory
162+ const mockedHealthChecker = {
163+ healthChecker : ( ) => createMockHealthChecker ( )
164+ } ;
177165
178- function setChainSyncyingStatus ( isSyncing : boolean ) : void {
179- getCurrentHealthChecker ( ) . _triggerHealthUpdate ( {
166+ // Helper function to set chain syncing status
167+ function setChainSyncyingStatus ( isSyncing : boolean ) {
168+ const health : SmoldotHealth = {
180169 isSyncing,
181170 peers : 1 ,
182171 shouldHavePeers : true
183- } ) ;
172+ } ;
173+ mockedHealthChecker . healthChecker ( ) . _update ( health ) ;
184174}
185175
186- let mockSc : MockSc ;
187- let mockedHealthChecker : ReturnType < typeof healthCheckerFactory > ;
188- const getCurrentHealthChecker = ( ) => mockedHealthChecker . _latestHealthChecker ( ) ;
176+ function createMockHealthChecker ( ) : HealthChecker & { _update : ( health : SmoldotHealth ) => void } {
177+ let sendRpc : ( ( req : string ) => void ) | null = null ;
178+ let healthCb : ( ( health : SmoldotHealth ) => void ) | null = null ;
179+
180+ return {
181+ setSendJsonRpc : ( cb ) => {
182+ sendRpc = cb ;
183+ } ,
184+ sendJsonRpc : ( req ) => sendRpc ?.( req ) ,
185+ responsePassThrough : ( res ) => res ,
186+ start : ( cb ) => {
187+ healthCb = cb ;
188+ } ,
189+ stop : ( ) => {
190+ healthCb = null ;
191+ } ,
192+ _update : ( health ) => healthCb ?.( health )
193+ } ;
194+ }
189195
190196describe ( 'ScProvider' , ( ) => {
191- beforeAll ( ( ) => {
192- mockSc = connectorFactory ( ) ;
193- mockedHealthChecker = healthCheckerFactory ( ) ;
197+ let provider : ScProvider ;
198+ let mockClient : ReturnType < typeof createMockClient > ;
199+ let mockHealthChecker : ReturnType < typeof createMockHealthChecker > ;
200+
201+ beforeEach ( async ( ) => {
202+ mockClient = createMockClient ( ) ;
203+ mockHealthChecker = createMockHealthChecker ( ) ;
204+ provider = new ScProvider ( { createScClient : ( ) => mockClient , WellKnownChain : mockWellKnownChain } , '' ) ;
205+ await provider . connect ( undefined , ( ) => mockHealthChecker ) ;
206+ } ) ;
207+
208+ afterEach ( async ( ) => {
209+ await provider . disconnect ( ) ;
194210 } ) ;
195211
196212 describe ( 'on' , ( ) => {
@@ -372,7 +388,7 @@ describe('ScProvider', () => {
372388
373389 setTimeout ( ( ) => {
374390 chain . _triggerCallback ( {
375- id : 1 ,
391+ id : 1 ,
376392 jsonrpc : '2.0'
377393 } ) ;
378394 } , 0 ) ;
@@ -488,8 +504,8 @@ describe('ScProvider', () => {
488504 } ) ;
489505 setTimeout ( ( ) => {
490506 chain . _triggerCallback ( {
491- id : 1 ,
492- jsonrpc : '2.0' ,
507+ id : 1 ,
508+ jsonrpc : '2.0' ,
493509 result : unsubscribeToken
494510 } ) ;
495511 } , 0 ) ;
@@ -519,8 +535,8 @@ describe('ScProvider', () => {
519535
520536 setTimeout ( ( ) => {
521537 chain . _triggerCallback ( {
522- id : 1 ,
523- jsonrpc : '2.0' ,
538+ id : 1 ,
539+ jsonrpc : '2.0' ,
524540 result : unsubscribeToken
525541 } ) ;
526542 } , 0 ) ;
0 commit comments