77@Timeout (Duration (minutes: 5 ))
88library ;
99
10+ import 'dart:async' ;
11+
1012import 'package:dwds/dwds.dart' ;
1113import 'package:dwds/expression_compiler.dart' ;
1214import 'package:test/test.dart' ;
@@ -32,26 +34,54 @@ void runTests({
3234
3335 tearDownAll (provider.dispose);
3436
35- Future <void > makeEditAndRecompile () async {
36- context.makeEditToDartEntryFile (
37- toReplace: originalString,
38- replaceWith: newString,
39- );
37+ Future <void > recompile ({bool hasEdits = false }) async {
4038 if (compilationMode == CompilationMode .frontendServer) {
4139 await context.recompile (fullRestart: true );
4240 } else {
4341 assert (compilationMode == CompilationMode .buildDaemon);
44- await context.waitForSuccessfulBuild (propagateToBrowser: true );
42+ if (hasEdits) {
43+ // Only gets a new build if there were edits.
44+ await context.waitForSuccessfulBuild (propagateToBrowser: true );
45+ }
4546 }
4647 }
4748
49+ Future <void > makeEditAndRecompile () async {
50+ context.makeEditToDartEntryFile (
51+ toReplace: originalString,
52+ replaceWith: newString,
53+ );
54+ await recompile (hasEdits: true );
55+ }
56+
4857 void undoEdit () {
4958 context.makeEditToDartEntryFile (
5059 toReplace: newString,
5160 replaceWith: originalString,
5261 );
5362 }
5463
64+ /// Wait for main to finish executing before checking expectations by checking
65+ /// for a log output.
66+ ///
67+ /// If [debuggingEnabled] is false, we can't check for Chrome logs and instead
68+ /// wait 1 second.
69+ // TODO(srujzs): We should do something less prone to race conditions when
70+ // debugging is disabled.
71+ Future <void > waitForMainToExecute ({bool debuggingEnabled = true }) async {
72+ if (! debuggingEnabled) return Future .delayed (const Duration (seconds: 1 ));
73+ final completer = Completer <void >();
74+ final expectedString = 'main executed' ;
75+ final subscription = context.webkitDebugger.onConsoleAPICalled.listen ((e) {
76+ if (e.args.first.value == expectedString) {
77+ completer.complete ();
78+ }
79+ });
80+ await completer.future.then ((_) {
81+ subscription.cancel ();
82+ });
83+ }
84+
5585 group (
5686 'Injected client with live reload' ,
5787 () {
@@ -74,7 +104,9 @@ void runTests({
74104 });
75105
76106 test ('can live reload changes ' , () async {
107+ final mainDone = waitForMainToExecute ();
77108 await makeEditAndRecompile ();
109+ await mainDone;
78110 final source = await context.webDriver.pageSource;
79111
80112 // A full reload should clear the state.
@@ -105,8 +137,9 @@ void runTests({
105137 });
106138
107139 test ('can live reload changes ' , () async {
140+ final mainDone = waitForMainToExecute (debuggingEnabled: false );
108141 await makeEditAndRecompile ();
109-
142+ await mainDone;
110143 final source = await context.webDriver.pageSource;
111144
112145 // A full reload should clear the state.
@@ -138,8 +171,9 @@ void runTests({
138171 });
139172
140173 test ('can live reload changes ' , () async {
174+ final mainDone = waitForMainToExecute (debuggingEnabled: false );
141175 await makeEditAndRecompile ();
142-
176+ await mainDone;
143177 final source = await context.webDriver.pageSource;
144178
145179 // A full reload should clear the state.
@@ -281,13 +315,15 @@ void runTests({
281315 ]),
282316 ),
283317 );
318+ final mainDone = waitForMainToExecute ();
284319 final hotRestart = context.getRegisteredServiceExtension ('hotRestart' );
285320 expect (
286321 await fakeClient.callServiceExtension (hotRestart! ),
287322 const TypeMatcher <Success >(),
288323 );
289324
290325 await eventsDone;
326+ await mainDone;
291327
292328 final source = await context.webDriver.pageSource;
293329 // Main is re-invoked which shouldn't clear the state.
@@ -324,6 +360,8 @@ void runTests({
324360 "registerExtension('ext.foo', $callback )" ,
325361 );
326362
363+ await recompile ();
364+ final mainDone = waitForMainToExecute ();
327365 final hotRestart = context.getRegisteredServiceExtension ('hotRestart' );
328366 expect (
329367 await fakeClient.callServiceExtension (hotRestart! ),
@@ -342,6 +380,7 @@ void runTests({
342380 );
343381
344382 await eventsDone;
383+ await mainDone;
345384
346385 final source = await context.webDriver.pageSource;
347386 // Main is re-invoked which shouldn't clear the state.
@@ -363,14 +402,15 @@ void runTests({
363402 ]),
364403 ),
365404 );
366-
405+ final mainDone = waitForMainToExecute ();
367406 final fullReload = context.getRegisteredServiceExtension ('fullReload' );
368407 expect (
369408 await fakeClient.callServiceExtension (fullReload! ),
370409 isA <Success >(),
371410 );
372411
373412 await eventsDone;
413+ await mainDone;
374414
375415 final source = await context.webDriver.pageSource;
376416 // Should see only the new text
@@ -399,8 +439,12 @@ void runTests({
399439 );
400440
401441 await makeEditAndRecompile ();
442+ final mainDone = waitForMainToExecute ();
402443 final hotRestart = context.getRegisteredServiceExtension ('hotRestart' );
403444 await fakeClient.callServiceExtension (hotRestart! );
445+
446+ await mainDone;
447+
404448 final source = await context.webDriver.pageSource;
405449
406450 // Main is re-invoked which shouldn't clear the state.
@@ -418,6 +462,7 @@ void runTests({
418462 test ('can evaluate expressions after hot restart' , () async {
419463 final client = context.debugConnection.vmService;
420464
465+ await recompile ();
421466 final hotRestart = context.getRegisteredServiceExtension ('hotRestart' );
422467 await fakeClient.callServiceExtension (hotRestart! );
423468
@@ -461,8 +506,9 @@ void runTests({
461506 });
462507
463508 test ('can hot restart changes ' , () async {
509+ final mainDone = waitForMainToExecute ();
464510 await makeEditAndRecompile ();
465-
511+ await mainDone;
466512 final source = await context.webDriver.pageSource;
467513
468514 // Main is re-invoked which shouldn't clear the state.
@@ -521,8 +567,9 @@ void runTests({
521567 });
522568
523569 test ('can hot restart changes ' , () async {
570+ final mainDone = waitForMainToExecute (debuggingEnabled: false );
524571 await makeEditAndRecompile ();
525-
572+ await mainDone;
526573 final source = await context.webDriver.pageSource;
527574
528575 // Main is re-invoked which shouldn't clear the state.
@@ -582,6 +629,7 @@ void runTests({
582629 ),
583630 );
584631
632+ final mainDone = waitForMainToExecute ();
585633 final hotRestart = context.getRegisteredServiceExtension ('hotRestart' );
586634 expect (
587635 await fakeClient.callServiceExtension (hotRestart! ),
@@ -597,6 +645,8 @@ void runTests({
597645 final isolateId = vm.isolates! .first.id! ;
598646 await client.resume (isolateId);
599647
648+ await mainDone;
649+
600650 final sourceAfterResume = await context.webDriver.pageSource;
601651 expect (sourceAfterResume.contains (newString), isTrue);
602652 },
@@ -605,8 +655,8 @@ void runTests({
605655 test (
606656 'after page refresh, does not run app until there is a resume event' ,
607657 () async {
658+ final mainDone = waitForMainToExecute ();
608659 await makeEditAndRecompile ();
609-
610660 await context.webDriver.driver.refresh ();
611661
612662 final eventsDone = expectLater (
@@ -629,6 +679,8 @@ void runTests({
629679 final isolateId = vm.isolates! .first.id! ;
630680 await client.resume (isolateId);
631681
682+ await mainDone;
683+
632684 final sourceAfterResume = await context.webDriver.pageSource;
633685 expect (sourceAfterResume.contains (newString), isTrue);
634686 },
0 commit comments