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