1
+ import { NightwatchBrowser } from 'nightwatch'
2
+ import init from '../../helpers/init'
3
+
4
+ const testContract = `
5
+ // SPDX-License-Identifier: MIT
6
+ pragma solidity ^0.8.0;
7
+
8
+ contract RemixMCPServerTest {
9
+ uint256 public testValue;
10
+ string public testString;
11
+
12
+ constructor(uint256 _value, string memory _str) {
13
+ testValue = _value;
14
+ testString = _str;
15
+ }
16
+
17
+ function updateValue(uint256 _newValue) public {
18
+ testValue = _newValue;
19
+ }
20
+
21
+ function updateString(string memory _newString) public {
22
+ testString = _newString;
23
+ }
24
+ }
25
+ ` ;
26
+
27
+ module . exports = {
28
+ '@disabled' : false ,
29
+ before : function ( browser : NightwatchBrowser , done : VoidFunction ) {
30
+ init ( browser , done )
31
+ } ,
32
+
33
+ 'Should verify RemixMCPServer initialization' : function ( browser : NightwatchBrowser ) {
34
+ browser
35
+ . waitForElementVisible ( '*[data-id="verticalIconsKindfilePanel"]' )
36
+ . click ( '*[data-id="verticalIconsKindaiTab"]' )
37
+ . waitForElementVisible ( '*[data-id="aiTabPanel"]' )
38
+ . execute ( function ( ) {
39
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
40
+ if ( ! aiPlugin ?. remixMCPServer ) {
41
+ return { error : 'RemixMCPServer not available' } ;
42
+ }
43
+
44
+ const server = aiPlugin . remixMCPServer ;
45
+ return {
46
+ hasRemixMcpServer : ! ! server ,
47
+ serverName : server . serverName || null ,
48
+ version : server . version || null ,
49
+ isInitialized : ! ! server . toolRegistry && ! ! server . resourceProviders ,
50
+ hasToolRegistry : ! ! server . toolRegistry ,
51
+ hasResourceProviders : ! ! server . resourceProviders ,
52
+ capabilities : server . capabilities || null
53
+ } ;
54
+ } , [ ] , function ( result ) {
55
+ const data = result . value as any ;
56
+ if ( data . error ) {
57
+ console . error ( 'RemixMCPServer error:' , data . error ) ;
58
+ return ;
59
+ }
60
+ browser . assert . ok ( data . hasRemixMcpServer , 'Should have RemixMCPServer instance' ) ;
61
+ browser . assert . ok ( data . isInitialized , 'Server should be properly initialized' ) ;
62
+ browser . assert . ok ( data . hasToolRegistry , 'Should have tool registry' ) ;
63
+ browser . assert . ok ( data . hasResourceProviders , 'Should have resource providers' ) ;
64
+ } ) ;
65
+ } ,
66
+
67
+ 'Should test RemixMCPServer tool registration' : function ( browser : NightwatchBrowser ) {
68
+ browser
69
+ . execute ( function ( ) {
70
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
71
+ if ( ! aiPlugin ?. remixMCPServer ?. toolRegistry ) {
72
+ return { error : 'Tool registry not available' } ;
73
+ }
74
+
75
+ const allTools = aiPlugin . remixMCPServer . tools ;
76
+ const compilationTools = allTools . filter ( ( t : any ) =>
77
+ t . name . includes ( 'compile' ) || t . category === 'COMPILATION'
78
+ ) ;
79
+
80
+ const deploymentTools = allTools . filter ( ( t : any ) =>
81
+ t . name . includes ( 'deploy' ) || t . name . includes ( 'account' ) || t . category === 'DEPLOYMENT'
82
+ ) ;
83
+
84
+ const fileTools = allTools . filter ( ( t : any ) =>
85
+ t . name . includes ( 'file' ) || t . category === 'FILE_SYSTEM'
86
+ ) ;
87
+
88
+ return {
89
+ totalTools : allTools . length ,
90
+ compilationToolCount : compilationTools . length ,
91
+ deploymentToolCount : deploymentTools . length ,
92
+ fileToolCount : fileTools . length ,
93
+ sampleTools : allTools . slice ( 0 , 3 ) . map ( ( t : any ) => ( {
94
+ name : t . name ,
95
+ category : t . category ,
96
+ hasHandler : ! ! t . handler
97
+ } ) )
98
+ } ;
99
+ } , [ ] , function ( result ) {
100
+ const data = result . value as any ;
101
+ if ( data . error ) {
102
+ console . error ( 'Tool registry error:' , data . error ) ;
103
+ return ;
104
+ }
105
+ browser . assert . ok ( data . totalTools > 0 , 'Should have registered tools' ) ;
106
+ browser . assert . ok ( data . compilationToolCount > 0 , 'Should have compilation tools' ) ;
107
+ browser . assert . ok ( data . deploymentToolCount > 0 , 'Should have deployment tools' ) ;
108
+ } ) ;
109
+ } ,
110
+
111
+ 'Should test RemixMCPServer resource providers' : function ( browser : NightwatchBrowser ) {
112
+ browser
113
+ . execute ( function ( ) {
114
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
115
+ if ( ! aiPlugin ?. remixMCPServer ?. resources ) {
116
+ return { error : 'Resource providers not available' } ;
117
+ }
118
+
119
+ const resourceProviders = aiPlugin . remixMCPServer . resources . providers ;
120
+ const deploymentProvider = resourceProviders . get ( 'deployment' ) ;
121
+ const projectProvider = resourceProviders . get ( 'project' ) ;
122
+ const compilerProvider = resourceProviders . get ( 'compiler' ) ;
123
+
124
+ return {
125
+ totalProviders : resourceProviders . size ,
126
+ hasDeploymentProvider : ! ! deploymentProvider ,
127
+ hasProjectProvider : ! ! projectProvider ,
128
+ hasCompilerProvider : ! ! compilerProvider ,
129
+ deploymentProviderMethods : deploymentProvider ? Object . getOwnPropertyNames ( Object . getPrototypeOf ( deploymentProvider ) ) : [ ] ,
130
+ projectProviderMethods : projectProvider ? Object . getOwnPropertyNames ( Object . getPrototypeOf ( projectProvider ) ) : [ ]
131
+ } ;
132
+ } , [ ] , function ( result ) {
133
+ const data = result . value as any ;
134
+ if ( data . error ) {
135
+ console . error ( 'Resource providers error:' , data . error ) ;
136
+ return ;
137
+ }
138
+ browser . assert . ok ( data . totalProviders > 0 , 'Should have resource providers' ) ;
139
+ browser . assert . ok ( data . hasDeploymentProvider , 'Should have deployment provider' ) ;
140
+ browser . assert . ok ( data . hasProjectProvider , 'Should have project provider' ) ;
141
+ } ) ;
142
+ } ,
143
+
144
+ 'Should test RemixMCPServer solidity compile tool execution via server' : function ( browser : NightwatchBrowser ) {
145
+ browser
146
+ . addFile ( 'contracts/RemixMCPServerTest.sol' , { content : testContract } )
147
+ . pause ( 1000 )
148
+ . execute ( async function ( ) {
149
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
150
+ if ( ! aiPlugin ?. remixMCPServer ) {
151
+ return { error : 'RemixMCPServer not available' } ;
152
+ }
153
+
154
+ try {
155
+ const server = aiPlugin . remixMCPServer ;
156
+
157
+ const compileResult = await server . executeTool ( {
158
+ name : 'solidity_compile' ,
159
+ arguments : {
160
+ file : 'contracts/RemixMCPServerTest.sol' ,
161
+ version : '0.8.20' ,
162
+ optimize : true ,
163
+ runs : 200
164
+ }
165
+ } ) ;
166
+
167
+ const configResult = await server . executeTool ( {
168
+ name : 'get_compiler_config' ,
169
+ arguments : { }
170
+ } ) ;
171
+
172
+ return {
173
+ compileExecuted : ! compileResult . isError ,
174
+ configExecuted : ! configResult . isError ,
175
+ compileContent : compileResult . content ?. [ 0 ] ?. text || null ,
176
+ configContent : configResult . content ?. [ 0 ] ?. text || null ,
177
+ compileError : compileResult . isError ? compileResult . content ?. [ 0 ] ?. text : null ,
178
+ configError : configResult . isError ? configResult . content ?. [ 0 ] ?. text : null
179
+ } ;
180
+ } catch ( error ) {
181
+ return { error : error . message } ;
182
+ }
183
+ } , [ ] , function ( result ) {
184
+ const data = result . value as any ;
185
+ if ( data . error ) {
186
+ console . error ( 'Server tool execution error:' , data . error ) ;
187
+ return ;
188
+ }
189
+ browser . assert . ok ( data . compileExecuted , 'Should execute compile tool successfully' ) ;
190
+ browser . assert . ok ( data . configExecuted , 'Should execute config tool successfully' ) ;
191
+ } ) ;
192
+ } ,
193
+
194
+ 'Should test RemixMCPServer main resources reading via server' : function ( browser : NightwatchBrowser ) {
195
+ browser
196
+ . execute ( async function ( ) {
197
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
198
+ if ( ! aiPlugin ?. remixMCPServer ) {
199
+ return { error : 'RemixMCPServer not available' } ;
200
+ }
201
+
202
+ try {
203
+ const server = aiPlugin . remixMCPServer ;
204
+
205
+ // Test resource reading through server
206
+ const historyResource = await server . readResource ( 'deployment://history' ) ;
207
+ const structureResource = await server . readResource ( 'project://structure' ) ;
208
+ const configResource = await server . readResource ( 'compiler://config' ) ;
209
+
210
+ return {
211
+ historyRead : ! ! historyResource ,
212
+ structureRead : ! ! structureResource ,
213
+ configRead : ! ! configResource ,
214
+ historyMimeType : historyResource ?. mimeType || null ,
215
+ structureMimeType : structureResource ?. mimeType || null ,
216
+ configMimeType : configResource ?. mimeType || null ,
217
+ historyHasContent : ! ! historyResource ?. text ,
218
+ structureHasContent : ! ! structureResource ?. text ,
219
+ configHasContent : ! ! configResource ?. text
220
+ } ;
221
+ } catch ( error ) {
222
+ return { error : error . message } ;
223
+ }
224
+ } , [ ] , function ( result ) {
225
+ const data = result . value as any ;
226
+ if ( data . error ) {
227
+ console . error ( 'Server resource reading error:' , data . error ) ;
228
+ return ;
229
+ }
230
+ browser . assert . ok ( data . historyRead , 'Should read deployment history resource' ) ;
231
+ browser . assert . ok ( data . structureRead , 'Should read project structure resource' ) ;
232
+ browser . assert . ok ( data . configRead , 'Should read compiler config resource' ) ;
233
+ } ) ;
234
+ } ,
235
+
236
+ 'Should test RemixMCPServer capabilities and metadata' : function ( browser : NightwatchBrowser ) {
237
+ browser
238
+ . execute ( function ( ) {
239
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
240
+ if ( ! aiPlugin ?. remixMCPServer ) {
241
+ return { error : 'RemixMCPServer not available' } ;
242
+ }
243
+
244
+ const server = aiPlugin . remixMCPServer ;
245
+
246
+ // Test server metadata and capabilities
247
+ const capabilities = server . capabilities || { } ;
248
+ const serverInfo = {
249
+ name : server . serverName ,
250
+ version : server . version ,
251
+ capabilities : capabilities
252
+ } ;
253
+
254
+ // Test tool and resource listing capabilities
255
+ const toolList = server . listTools ? server . listTools ( ) : null ;
256
+ const resourceList = server . listResources ? server . listResources ( ) : null ;
257
+
258
+ return {
259
+ serverInfo,
260
+ hasCapabilities : Object . keys ( capabilities ) . length > 0 ,
261
+ supportsTools : ! ! capabilities . tools ,
262
+ supportsResources : ! ! capabilities . resources ,
263
+ toolListAvailable : ! ! toolList ,
264
+ resourceListAvailable : ! ! resourceList ,
265
+ toolCount : toolList ? toolList . length : 0 ,
266
+ resourceCount : resourceList ? resourceList . length : 0
267
+ } ;
268
+ } , [ ] , function ( result ) {
269
+ const data = result . value as any ;
270
+ if ( data . error ) {
271
+ console . error ( 'Server capabilities error:' , data . error ) ;
272
+ return ;
273
+ }
274
+ browser . assert . ok ( data . hasCapabilities , 'Should have server capabilities' ) ;
275
+ browser . assert . ok ( data . supportsTools , 'Should support tools' ) ;
276
+ browser . assert . ok ( data . toolCount > 0 , 'Should tools' ) ;
277
+ browser . assert . ok ( data . resourceCount > 0 , 'Should resources' ) ;
278
+ browser . assert . ok ( data . supportsResources , 'Should support resources' ) ;
279
+ } ) ;
280
+ } ,
281
+
282
+ 'Should test RemixMCPServer error handling invalid tool execution' : function ( browser : NightwatchBrowser ) {
283
+ browser
284
+ . execute ( async function ( ) {
285
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
286
+ if ( ! aiPlugin ?. remixMCPServer ) {
287
+ return { error : 'RemixMCPServer not available' } ;
288
+ }
289
+
290
+ try {
291
+ const server = aiPlugin . remixMCPServer ;
292
+
293
+ let invalidToolResult ;
294
+ try {
295
+ invalidToolResult = await server . executeTool ( {
296
+ name : 'non_existent_tool' ,
297
+ arguments : { }
298
+ } ) ;
299
+ } catch ( error ) {
300
+ invalidToolResult = { isError : true , content : [ { text : error . message } ] } ;
301
+ }
302
+
303
+ let invalidResourceResult ;
304
+ try {
305
+ invalidResourceResult = await server . readResource ( 'invalid://resource' ) ;
306
+ } catch ( error ) {
307
+ invalidResourceResult = null ;
308
+ }
309
+
310
+ let invalidArgsResult ;
311
+ try {
312
+ invalidArgsResult = await server . executeTool ( {
313
+ name : 'solidity_compile' ,
314
+ arguments : {
315
+ runs : 99999 // Invalid: too high
316
+ }
317
+ } ) ;
318
+ } catch ( error ) {
319
+ invalidArgsResult = { isError : true , content : [ { text : error . message } ] } ;
320
+ }
321
+
322
+ return {
323
+ invalidToolHandled : invalidToolResult ?. isError === true ,
324
+ invalidResourceHandled : invalidResourceResult === null ,
325
+ invalidArgsHandled : invalidArgsResult ?. isError === true ,
326
+ systemStable : true ,
327
+ invalidToolMessage : invalidToolResult ?. content ?. [ 0 ] ?. text || 'No message' ,
328
+ invalidArgsMessage : invalidArgsResult ?. content ?. [ 0 ] ?. text || 'No message'
329
+ } ;
330
+ } catch ( error ) {
331
+ return { error : error . message } ;
332
+ }
333
+ } , [ ] , function ( result ) {
334
+ const data = result . value as any ;
335
+ if ( data . error ) {
336
+ console . error ( 'Server error handling test error:' , data . error ) ;
337
+ return ;
338
+ }
339
+ browser . assert . ok ( data . invalidToolHandled , 'Should handle invalid tools gracefully' ) ;
340
+ browser . assert . ok ( data . invalidResourceHandled , 'Should handle invalid resources gracefully' ) ;
341
+ browser . assert . ok ( data . invalidArgsHandled , 'Should handle invalid arguments gracefully' ) ;
342
+ browser . assert . ok ( data . systemStable , 'System should remain stable after errors' ) ;
343
+ } ) ;
344
+ } ,
345
+
346
+ 'Should test RemixMCPServer performance and caching' : function ( browser : NightwatchBrowser ) {
347
+ browser
348
+ . execute ( async function ( ) {
349
+ const aiPlugin = ( window as any ) . getRemixAIPlugin ( ) ;
350
+ if ( ! aiPlugin ?. remixMCPServer ) {
351
+ return { error : 'RemixMCPServer not available' } ;
352
+ }
353
+
354
+ try {
355
+ const server = aiPlugin . remixMCPServer ;
356
+ const startTime = Date . now ( ) ;
357
+
358
+ // Test multiple operations for performance
359
+ const operations = await Promise . all ( [
360
+ server . readResource ( 'deployment://history' ) ,
361
+ server . readResource ( 'project://structure' ) ,
362
+ ] ) ;
363
+
364
+ const endTime = Date . now ( ) ;
365
+ const totalTime = endTime - startTime ;
366
+
367
+ // Test caching behavior
368
+ const cachingStart = Date . now ( ) ;
369
+ const cachedResource1 = await server . readResource ( 'deployment://history' ) ;
370
+ const cachedResource2 = await server . readResource ( 'project://structure' ) ;
371
+ const cachingEnd = Date . now ( ) ;
372
+ const cachingTime = cachingEnd - cachingStart ;
373
+
374
+ return {
375
+ operationsCompleted : operations . length ,
376
+ totalExecutionTime : totalTime ,
377
+ averageOperationTime : totalTime / operations . length ,
378
+ cachingTime,
379
+ allOperationsSucceeded : operations . every ( op => ! ! op ) ,
380
+ performanceAcceptable : totalTime < 1000 , // Should complete within 5 seconds
381
+ cachingWorking : cachingTime < totalTime // Caching should be faster
382
+ } ;
383
+ } catch ( error ) {
384
+ return { error : error . message } ;
385
+ }
386
+ } , [ ] , function ( result ) {
387
+ const data = result . value as any ;
388
+ if ( data . error ) {
389
+ console . error ( 'Performance test error:' , data . error ) ;
390
+ return ;
391
+ }
392
+ browser . assert . ok ( data . allOperationsSucceeded , 'All operations should succeed' ) ;
393
+ browser . assert . ok ( data . performanceAcceptable , 'Performance should be acceptable' ) ;
394
+ browser . assert . equal ( data . operationsCompleted , 5 , 'Should complete all test operations' ) ;
395
+ } ) ;
396
+ }
397
+ } ;
0 commit comments