Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dwds/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## 25.1.0-wip

## 25.0.1

### Bug Fixes:
Expand Down
2 changes: 1 addition & 1 deletion dwds/lib/src/version.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dwds/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: dwds
# Every time this changes you need to run `dart run build_runner build`.
version: 25.0.1
version: 25.1.0-wip

description: >-
A service that proxies between the Chrome debug protocol and the Dart VM
Expand Down
194 changes: 68 additions & 126 deletions dwds/test/common/hot_restart_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,27 @@ void runTests({
}

Future<void> makeEditAndRecompile() async {
context.makeEditToDartEntryFile(
toReplace: originalString,
replaceWith: newString,
);
await context.makeEdits([
(
file: context.project.dartEntryFileName,
originalString: originalString,
newString: newString,
),
]);
await recompile(hasEdits: true);
}

/// Wait for main to finish executing before checking expectations by checking
/// for a log output.
///
/// If [debuggingEnabled] is false, we can't check for Chrome logs and instead
/// wait 1 second.
// TODO(srujzs): We should do something less prone to race conditions when
// debugging is disabled.
Future<void> waitForMainToExecute({bool debuggingEnabled = true}) async {
if (!debuggingEnabled) return Future.delayed(const Duration(seconds: 1));
/// Wait for `expectedStrings` to be printed in the console.
Future<void> expectLogs(List<String> expectedStrings) async {
final expectations = List<String>.from(expectedStrings);
final completer = Completer<void>();
final expectedString = 'main executed';
final subscription = context.webkitDebugger.onConsoleAPICalled.listen((e) {
if (e.args.first.value == expectedString) {
completer.complete();
final value = e.args.first.value;
if (expectations.contains(value)) {
expectations.remove(value);
if (expectations.isEmpty) {
completer.complete();
}
}
});
await completer.future;
Expand Down Expand Up @@ -95,14 +95,10 @@ void runTests({
});

test('can live reload changes ', () async {
final mainDone = waitForMainToExecute();
await makeEditAndRecompile();
await mainDone;
final source = await context.webDriver.pageSource;

// A full reload should clear the state.
expect(source.contains(originalString), isFalse);
expect(source.contains(newString), isTrue);
final logExpectation = expectLogs([newString]);
await makeEditAndRecompile();
await logExpectation;
});
});

Expand All @@ -127,14 +123,10 @@ void runTests({
});

test('can live reload changes ', () async {
final mainDone = waitForMainToExecute(debuggingEnabled: false);
await makeEditAndRecompile();
await mainDone;
final source = await context.webDriver.pageSource;

// A full reload should clear the state.
expect(source.contains(originalString), isFalse);
expect(source.contains(newString), isTrue);
final logExpectation = expectLogs([newString]);
await makeEditAndRecompile();
await logExpectation;
});
});

Expand All @@ -160,14 +152,10 @@ void runTests({
});

test('can live reload changes ', () async {
final mainDone = waitForMainToExecute(debuggingEnabled: false);
await makeEditAndRecompile();
await mainDone;
final source = await context.webDriver.pageSource;

// A full reload should clear the state.
expect(source.contains(originalString), isFalse);
expect(source.contains(newString), isTrue);
final logExpectation = expectLogs([newString]);
await makeEditAndRecompile();
await logExpectation;
});
});
},
Expand Down Expand Up @@ -303,20 +291,16 @@ void runTests({
]),
),
);
final mainDone = waitForMainToExecute();
// Main is re-invoked which shouldn't clear the state.
final logExpectation = expectLogs(['$originalString $newString']);
final hotRestart = context.getRegisteredServiceExtension('hotRestart');
expect(
await fakeClient.callServiceExtension(hotRestart!),
const TypeMatcher<Success>(),
);

await eventsDone;
await mainDone;

final source = await context.webDriver.pageSource;
// Main is re-invoked which shouldn't clear the state.
expect(source, contains(originalString));
expect(source, contains(newString));
await logExpectation;
});

test('can send events before and after hot restart', () async {
Expand Down Expand Up @@ -349,7 +333,8 @@ void runTests({
);

await recompile();
final mainDone = waitForMainToExecute();
// Main is re-invoked which shouldn't clear the state.
final logExpectation = expectLogs(['$originalString $originalString']);
final hotRestart = context.getRegisteredServiceExtension('hotRestart');
expect(
await fakeClient.callServiceExtension(hotRestart!),
Expand All @@ -368,11 +353,7 @@ void runTests({
);

await eventsDone;
await mainDone;

final source = await context.webDriver.pageSource;
// Main is re-invoked which shouldn't clear the state.
expect(source, contains('Hello World!'));
await logExpectation;
});

test('can refresh the page via the fullReload service extension', () async {
Expand All @@ -390,20 +371,16 @@ void runTests({
]),
),
);
final mainDone = waitForMainToExecute();
// Should see only the new text.
final logExpectation = expectLogs([newString]);
final fullReload = context.getRegisteredServiceExtension('fullReload');
expect(
await fakeClient.callServiceExtension(fullReload!),
isA<Success>(),
);

await eventsDone;
await mainDone;

final source = await context.webDriver.pageSource;
// Should see only the new text
expect(source.contains(originalString), isFalse);
expect(source.contains(newString), isTrue);
await logExpectation;
});

test('can hot restart while paused', () async {
Expand All @@ -427,17 +404,11 @@ void runTests({
);

await makeEditAndRecompile();
final mainDone = waitForMainToExecute();
// Main is re-invoked which shouldn't clear the state.
final logExpectation = expectLogs(['$originalString $newString']);
final hotRestart = context.getRegisteredServiceExtension('hotRestart');
await fakeClient.callServiceExtension(hotRestart!);

await mainDone;

final source = await context.webDriver.pageSource;

// Main is re-invoked which shouldn't clear the state.
expect(source.contains(originalString), isTrue);
expect(source.contains(newString), isTrue);
await logExpectation;

vm = await client.getVM();
isolateId = vm.isolates!.first.id!;
Expand Down Expand Up @@ -474,37 +445,27 @@ void runTests({
test('can hot restart with no changes, hot restart with changes, and '
'hot restart again with no changes', () async {
// Empty hot restart.
var mainDone = waitForMainToExecute();
var logExpectation = expectLogs(['$originalString $originalString']);
await recompile();
final hotRestart = context.getRegisteredServiceExtension('hotRestart');
await fakeClient.callServiceExtension(hotRestart!);

await mainDone;
var source = await context.webDriver.pageSource;
expect(source.contains(originalString), isTrue);
expect(source.contains(newString), isFalse);
await logExpectation;

// Hot restart.
mainDone = waitForMainToExecute();
logExpectation = expectLogs([
'$originalString $originalString $newString',
]);
await makeEditAndRecompile();
await fakeClient.callServiceExtension(hotRestart);

await mainDone;
source = await context.webDriver.pageSource;
// Main is re-invoked which shouldn't clear the state.
expect(source.contains(originalString), isTrue);
expect(source.contains(newString), isTrue);
await logExpectation;

// Empty hot restart.
mainDone = waitForMainToExecute();
logExpectation = expectLogs([
'$originalString $originalString $newString $newString',
]);
await recompile();
await fakeClient.callServiceExtension(hotRestart);

await mainDone;
source = await context.webDriver.pageSource;
expect(source.contains(originalString), isTrue);
// `newString` should now exist twice in the source.
expect(source.contains(RegExp('$newString.*$newString')), isTrue);
await logExpectation;
});
}, timeout: Timeout.factor(2));

Expand All @@ -529,19 +490,15 @@ void runTests({
});

test('can hot restart changes ', () async {
final mainDone = waitForMainToExecute();
await makeEditAndRecompile();
await mainDone;
final source = await context.webDriver.pageSource;

// Main is re-invoked which shouldn't clear the state.
expect(source.contains(originalString), isTrue);
expect(source.contains(newString), isTrue);
// The ext.flutter.disassemble callback is invoked and waited for.
expect(
source,
contains('start disassemble end disassemble $newString'),
);
final logExpectations = expectLogs([
'$originalString $newString',
// The ext.flutter.disassemble callback is invoked and waited for.
'start disassemble',
'end disassemble',
]);
await makeEditAndRecompile();
await logExpectations;
});

test(
Expand Down Expand Up @@ -589,19 +546,15 @@ void runTests({
});

test('can hot restart changes ', () async {
final mainDone = waitForMainToExecute(debuggingEnabled: false);
await makeEditAndRecompile();
await mainDone;
final source = await context.webDriver.pageSource;

// Main is re-invoked which shouldn't clear the state.
expect(source.contains(originalString), isTrue);
expect(source.contains(newString), isTrue);
// The ext.flutter.disassemble callback is invoked and waited for.
expect(
source,
contains('start disassemble end disassemble $newString'),
);
final logExpectations = expectLogs([
'$originalString $newString',
// The ext.flutter.disassemble callback is invoked and waited for.
'start disassemble',
'end disassemble',
]);
await makeEditAndRecompile();
await logExpectations;
});
});
},
Expand Down Expand Up @@ -650,7 +603,8 @@ void runTests({
),
);

final mainDone = waitForMainToExecute();
// Main is re-invoked which shouldn't clear the state.
final logExpectation = expectLogs(['$originalString $newString']);
final hotRestart = context.getRegisteredServiceExtension('hotRestart');
expect(
await fakeClient.callServiceExtension(hotRestart!),
Expand All @@ -659,24 +613,18 @@ void runTests({

await eventsDone;

final sourceBeforeResume = await context.webDriver.pageSource;
expect(sourceBeforeResume.contains(newString), isFalse);

final vm = await client.getVM();
final isolateId = vm.isolates!.first.id!;
await client.resume(isolateId);

await mainDone;

final sourceAfterResume = await context.webDriver.pageSource;
expect(sourceAfterResume.contains(newString), isTrue);
await logExpectation;
},
);

test(
'after page refresh, does not run app until there is a resume event',
() async {
final mainDone = waitForMainToExecute();
final logExpectation = expectLogs([newString]);
await makeEditAndRecompile();
await context.webDriver.driver.refresh();

Expand All @@ -693,17 +641,11 @@ void runTests({

await eventsDone;

final sourceBeforeResume = await context.webDriver.pageSource;
expect(sourceBeforeResume.contains(newString), isFalse);

final vm = await client.getVM();
final isolateId = vm.isolates!.first.id!;
await client.resume(isolateId);

await mainDone;

final sourceAfterResume = await context.webDriver.pageSource;
expect(sourceAfterResume.contains(newString), isTrue);
await logExpectation;
},
);
});
Expand Down
Loading
Loading