@@ -197,6 +197,207 @@ void main() {
197
197
await client.shutdown ();
198
198
},
199
199
);
200
+
201
+ test.test ('launch_app tool fails when process exits early' , () async {
202
+ final mockProcessManager = MockProcessManager ();
203
+ mockProcessManager.addCommand (
204
+ Command (
205
+ [
206
+ Platform .isWindows
207
+ ? r'C:\path\to\flutter\sdk\bin\cache\dart-sdk\bin\dart.exe'
208
+ : '/path/to/flutter/sdk/bin/cache/dart-sdk/bin/dart' ,
209
+ 'language-server' ,
210
+ '--protocol' ,
211
+ 'lsp' ,
212
+ ],
213
+ stdout:
214
+ '''Content-Length: 145\r\n\r\n {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":true}},"workspaceSymbolProvider":true}}}''' ,
215
+ ),
216
+ );
217
+ mockProcessManager.addCommand (
218
+ Command (
219
+ [
220
+ Platform .isWindows
221
+ ? r'C:\path\to\flutter\sdk\bin\flutter.bat'
222
+ : '/path/to/flutter/sdk/bin/flutter' ,
223
+ 'run' ,
224
+ '--print-dtd' ,
225
+ '--device-id' ,
226
+ 'test-device' ,
227
+ ],
228
+ stderr: 'Something went wrong' ,
229
+ exitCode: Future .value (1 ),
230
+ ),
231
+ );
232
+ final serverAndClient = await createServerAndClient (
233
+ processManager: mockProcessManager,
234
+ fileSystem: fileSystem,
235
+ );
236
+ final server = serverAndClient.server;
237
+ final client = serverAndClient.client;
238
+
239
+ // Initialize
240
+ await client.initialize (
241
+ InitializeRequest (
242
+ protocolVersion: ProtocolVersion .latestSupported,
243
+ capabilities: ClientCapabilities (),
244
+ clientInfo: Implementation (name: 'test_client' , version: '1.0.0' ),
245
+ ),
246
+ );
247
+ client.notifyInitialized ();
248
+
249
+ // Call the tool
250
+ final result = await client.callTool (
251
+ CallToolRequest (
252
+ name: 'launch_app' ,
253
+ arguments: {'root' : projectRoot, 'device' : 'test-device' },
254
+ ),
255
+ );
256
+
257
+ test.expect (result.isError, true );
258
+ final textOutput = result.content as List <TextContent >;
259
+ test.expect (
260
+ textOutput.map ((context) => context.text).toList ().join ('\n ' ),
261
+ test.stringContainsInOrder ([
262
+ 'Flutter application exited with code 1 before the DTD URI was found' ,
263
+ 'with log output' ,
264
+ 'Something went wrong' ,
265
+ ]),
266
+ );
267
+ await server.shutdown ();
268
+ await client.shutdown ();
269
+ });
270
+
271
+ test.test ('stop_app tool stops a running app' , () async {
272
+ final dtdUri = 'ws://127.0.0.1:12345/abcdefg=' ;
273
+ final processPid = 54321 ;
274
+ final mockProcessManager = MockProcessManager ();
275
+ mockProcessManager.addCommand (
276
+ Command (
277
+ [
278
+ Platform .isWindows
279
+ ? r'C:\path\to\flutter\sdk\bin\cache\dart-sdk\bin\dart.exe'
280
+ : '/path/to/flutter/sdk/bin/cache/dart-sdk/bin/dart' ,
281
+ 'language-server' ,
282
+ '--protocol' ,
283
+ 'lsp' ,
284
+ ],
285
+ stdout:
286
+ '''Content-Length: 145\r\n\r\n {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":true}},"workspaceSymbolProvider":true}}}
287
+ ''' ,
288
+ ),
289
+ );
290
+ mockProcessManager.addCommand (
291
+ Command (
292
+ [
293
+ Platform .isWindows
294
+ ? r'C:\path\to\flutter\sdk\bin\flutter.bat'
295
+ : '/path/to/flutter/sdk/bin/flutter' ,
296
+ 'run' ,
297
+ '--print-dtd' ,
298
+ '--device-id' ,
299
+ 'test-device' ,
300
+ ],
301
+ stdout: 'The Dart Tooling Daemon is available at: $dtdUri \n ' ,
302
+ pid: processPid,
303
+ ),
304
+ );
305
+ final serverAndClient = await createServerAndClient (
306
+ processManager: mockProcessManager,
307
+ fileSystem: fileSystem,
308
+ );
309
+ final server = serverAndClient.server;
310
+ final client = serverAndClient.client;
311
+
312
+ // Initialize and launch the app
313
+ await client.initialize (
314
+ InitializeRequest (
315
+ protocolVersion: ProtocolVersion .latestSupported,
316
+ capabilities: ClientCapabilities (),
317
+ clientInfo: Implementation (name: 'test_client' , version: '1.0.0' ),
318
+ ),
319
+ );
320
+ client.notifyInitialized ();
321
+ await client.callTool (
322
+ CallToolRequest (
323
+ name: 'launch_app' ,
324
+ arguments: {'root' : projectRoot, 'device' : 'test-device' },
325
+ ),
326
+ );
327
+
328
+ // Stop the app
329
+ final result = await client.callTool (
330
+ CallToolRequest (name: 'stop_app' , arguments: {'pid' : processPid}),
331
+ );
332
+
333
+ test.expect (result.isError, test.isNot (true ));
334
+ test.expect (result.structuredContent, {'success' : true });
335
+ test.expect (mockProcessManager.killedPids, [processPid]);
336
+ await server.shutdown ();
337
+ await client.shutdown ();
338
+ });
339
+
340
+ test.test ('list_devices tool returns available devices' , () async {
341
+ final mockProcessManager = MockProcessManager ();
342
+ mockProcessManager.addCommand (
343
+ Command (
344
+ [
345
+ Platform .isWindows
346
+ ? r'C:\path\to\flutter\sdk\bin\cache\dart-sdk\bin\dart.exe'
347
+ : '/path/to/flutter/sdk/bin/cache/dart-sdk/bin/dart' ,
348
+ 'language-server' ,
349
+ '--protocol' ,
350
+ 'lsp' ,
351
+ ],
352
+ stdout:
353
+ '''Content-Length: 145\r\n\r\n {"jsonrpc":"2.0","id":0,"result":{"capabilities":{"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":true}},"workspaceSymbolProvider":true}}}
354
+ ''' ,
355
+ ),
356
+ );
357
+ mockProcessManager.addCommand (
358
+ Command (
359
+ [
360
+ Platform .isWindows
361
+ ? r'C:\path\to\flutter\sdk\bin\flutter.bat'
362
+ : '/path/to/flutter/sdk/bin/flutter' ,
363
+ 'devices' ,
364
+ '--machine' ,
365
+ ],
366
+ stdout: jsonEncode ([
367
+ {'id' : 'test-device-1' },
368
+ {'id' : 'test-device-2' },
369
+ ]),
370
+ ),
371
+ );
372
+ final serverAndClient = await createServerAndClient (
373
+ processManager: mockProcessManager,
374
+ fileSystem: fileSystem,
375
+ );
376
+ final server = serverAndClient.server;
377
+ final client = serverAndClient.client;
378
+
379
+ // Initialize
380
+ await client.initialize (
381
+ InitializeRequest (
382
+ protocolVersion: ProtocolVersion .latestSupported,
383
+ capabilities: ClientCapabilities (),
384
+ clientInfo: Implementation (name: 'test_client' , version: '1.0.0' ),
385
+ ),
386
+ );
387
+ client.notifyInitialized ();
388
+
389
+ // List devices
390
+ final result = await client.callTool (
391
+ CallToolRequest (name: 'list_devices' , arguments: {}),
392
+ );
393
+
394
+ test.expect (result.isError, test.isNot (true ));
395
+ test.expect (result.structuredContent, {
396
+ 'devices' : ['test-device-1' , 'test-device-2' ],
397
+ });
398
+ await server.shutdown ();
399
+ await client.shutdown ();
400
+ });
200
401
});
201
402
}
202
403
0 commit comments