mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
263 lines
9.6 KiB
Dart
263 lines
9.6 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:file/file.dart';
|
|
import 'package:vm_service/vm_service.dart';
|
|
|
|
import '../integration.shard/test_data/basic_project.dart';
|
|
import '../integration.shard/test_data/tests_project.dart';
|
|
import '../integration.shard/test_driver.dart';
|
|
import '../integration.shard/test_utils.dart';
|
|
import '../src/common.dart';
|
|
|
|
void main() {
|
|
group('Flutter run for web', () {
|
|
final BasicProject project = BasicProject();
|
|
late Directory tempDir;
|
|
late FlutterRunTestDriver flutter;
|
|
|
|
setUp(() async {
|
|
tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
|
|
await project.setUpIn(tempDir);
|
|
flutter = FlutterRunTestDriver(tempDir);
|
|
flutter.stdout.listen((String line) {
|
|
expect(line, isNot(contains('Unresolved uri:')));
|
|
});
|
|
});
|
|
|
|
tearDown(() async {
|
|
await flutter.stop();
|
|
tryToDelete(tempDir);
|
|
});
|
|
|
|
Future<void> start({required bool expressionEvaluation}) async {
|
|
// The non-test project has a loop around its breakpoints.
|
|
// No need to start paused as all breakpoint would be eventually reached.
|
|
await flutter.run(
|
|
withDebugger: true, chrome: true,
|
|
expressionEvaluation: expressionEvaluation,
|
|
additionalCommandArgs: <String>['--verbose', '--web-renderer=html']);
|
|
}
|
|
|
|
Future<void> breakInBuildMethod(FlutterTestDriver flutter) async {
|
|
await flutter.breakAt(
|
|
project.buildMethodBreakpointUri,
|
|
project.buildMethodBreakpointLine,
|
|
);
|
|
}
|
|
|
|
Future<void> breakInTopLevelFunction(FlutterTestDriver flutter) async {
|
|
await flutter.breakAt(
|
|
project.topLevelFunctionBreakpointUri,
|
|
project.topLevelFunctionBreakpointLine,
|
|
);
|
|
}
|
|
|
|
testWithoutContext('cannot evaluate expression if feature is disabled', () async {
|
|
await start(expressionEvaluation: false);
|
|
await breakInTopLevelFunction(flutter);
|
|
await failToEvaluateExpression(flutter);
|
|
});
|
|
|
|
testWithoutContext('shows no native javascript objects in static scope', () async {
|
|
await start(expressionEvaluation: true);
|
|
await breakInTopLevelFunction(flutter);
|
|
await checkStaticScope(flutter);
|
|
});
|
|
|
|
testWithoutContext('can handle compilation errors', () async {
|
|
await start(expressionEvaluation: true);
|
|
await breakInTopLevelFunction(flutter);
|
|
await evaluateErrorExpressions(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate trivial expressions in top level function', () async {
|
|
await start(expressionEvaluation: true);
|
|
await breakInTopLevelFunction(flutter);
|
|
await evaluateTrivialExpressions(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate trivial expressions in build method', () async {
|
|
await start(expressionEvaluation: true);
|
|
await breakInBuildMethod(flutter);
|
|
await evaluateTrivialExpressions(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate complex expressions in top level function', () async {
|
|
await start(expressionEvaluation: true);
|
|
await breakInTopLevelFunction(flutter);
|
|
await evaluateComplexExpressions(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate complex expressions in build method', () async {
|
|
await start(expressionEvaluation: true);
|
|
await breakInBuildMethod(flutter);
|
|
await evaluateComplexExpressions(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate trivial expressions in library without pause', () async {
|
|
await start(expressionEvaluation: true);
|
|
await evaluateTrivialExpressionsInLibrary(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate complex expressions in library without pause', () async {
|
|
await start(expressionEvaluation: true);
|
|
await evaluateComplexExpressionsInLibrary(flutter);
|
|
});
|
|
|
|
testWithoutContext('evaluated expression includes web library environment defines', () async {
|
|
await start(expressionEvaluation: true);
|
|
await evaluateWebLibraryBooleanFromEnvironmentInLibrary(flutter);
|
|
});
|
|
});
|
|
|
|
group('Flutter test for web', () {
|
|
final TestsProject project = TestsProject();
|
|
late Directory tempDir;
|
|
late FlutterRunTestDriver flutter;
|
|
|
|
setUp(() async {
|
|
tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
|
|
await project.setUpIn(tempDir);
|
|
flutter = FlutterRunTestDriver(tempDir);
|
|
});
|
|
|
|
tearDown(() async {
|
|
await flutter.stop();
|
|
tryToDelete(tempDir);
|
|
});
|
|
|
|
Future<Isolate?> breakInMethod(FlutterTestDriver flutter) async {
|
|
await flutter.addBreakpoint(
|
|
project.breakpointAppUri,
|
|
project.breakpointLine,
|
|
);
|
|
return flutter.resume(waitForNextPause: true);
|
|
}
|
|
|
|
Future<void> startPaused({required bool expressionEvaluation}) {
|
|
// The test project does not have a loop around its breakpoints.
|
|
// Start paused so we can set a breakpoint before passing it
|
|
// in the execution.
|
|
return flutter.run(
|
|
withDebugger: true, chrome: true,
|
|
expressionEvaluation: expressionEvaluation,
|
|
startPaused: true, script: project.testFilePath,
|
|
additionalCommandArgs: <String>['--verbose', '--web-renderer=html']);
|
|
}
|
|
|
|
testWithoutContext('cannot evaluate expressions if feature is disabled', () async {
|
|
await startPaused(expressionEvaluation: false);
|
|
await breakInMethod(flutter);
|
|
await failToEvaluateExpression(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate trivial expressions in a test', () async {
|
|
await startPaused(expressionEvaluation: true);
|
|
await breakInMethod(flutter);
|
|
await evaluateTrivialExpressions(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate complex expressions in a test', () async {
|
|
await startPaused(expressionEvaluation: true);
|
|
await breakInMethod(flutter);
|
|
await evaluateComplexExpressions(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate trivial expressions in library without pause', () async {
|
|
await startPaused(expressionEvaluation: true);
|
|
await evaluateTrivialExpressionsInLibrary(flutter);
|
|
});
|
|
|
|
testWithoutContext('can evaluate complex expressions in library without pause', () async {
|
|
await startPaused(expressionEvaluation: true);
|
|
await evaluateComplexExpressionsInLibrary(flutter);
|
|
});
|
|
testWithoutContext('evaluated expression includes web library environment defines', () async {
|
|
await startPaused(expressionEvaluation: true);
|
|
await evaluateWebLibraryBooleanFromEnvironmentInLibrary(flutter);
|
|
});
|
|
});
|
|
}
|
|
|
|
Future<void> failToEvaluateExpression(FlutterTestDriver flutter) async {
|
|
await expectLater(
|
|
flutter.evaluateInFrame('"test"'),
|
|
throwsA(isA<RPCError>().having(
|
|
(RPCError error) => error.message,
|
|
'message',
|
|
contains('Expression evaluation is not supported for this configuration'),
|
|
)),
|
|
);
|
|
}
|
|
|
|
Future<void> checkStaticScope(FlutterTestDriver flutter) async {
|
|
final Frame res = await flutter.getTopStackFrame();
|
|
expect(res.vars, equals(<BoundVariable>[]));
|
|
}
|
|
|
|
Future<void> evaluateErrorExpressions(FlutterTestDriver flutter) async {
|
|
final ObjRef res = await flutter.evaluateInFrame('typo');
|
|
expectError(res, 'CompilationError:');
|
|
}
|
|
|
|
Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
|
|
ObjRef res;
|
|
|
|
res = await flutter.evaluateInFrame('"test"');
|
|
expectInstance(res, InstanceKind.kString, 'test');
|
|
|
|
res = await flutter.evaluateInFrame('1');
|
|
expectInstance(res, InstanceKind.kDouble, 1.toString());
|
|
|
|
res = await flutter.evaluateInFrame('true');
|
|
expectInstance(res, InstanceKind.kBool, true.toString());
|
|
}
|
|
|
|
Future<void> evaluateComplexExpressions(FlutterTestDriver flutter) async {
|
|
final ObjRef res = await flutter.evaluateInFrame('new DateTime.now().year');
|
|
expectInstance(res, InstanceKind.kDouble, DateTime.now().year.toString());
|
|
}
|
|
|
|
Future<void> evaluateTrivialExpressionsInLibrary(FlutterTestDriver flutter) async {
|
|
final LibraryRef library = await getRootLibrary(flutter);
|
|
final ObjRef res = await flutter.evaluate(library.id!, '"test"');
|
|
expectInstance(res, InstanceKind.kString, 'test');
|
|
}
|
|
|
|
Future<void> evaluateComplexExpressionsInLibrary(FlutterTestDriver flutter) async {
|
|
final LibraryRef library = await getRootLibrary(flutter);
|
|
final ObjRef res = await flutter.evaluate(library.id!, 'new DateTime.now().year');
|
|
expectInstance(res, InstanceKind.kDouble, DateTime.now().year.toString());
|
|
}
|
|
|
|
Future<void> evaluateWebLibraryBooleanFromEnvironmentInLibrary(FlutterTestDriver flutter) async {
|
|
final LibraryRef library = await getRootLibrary(flutter);
|
|
final ObjRef res = await flutter.evaluate(library.id!, 'const bool.fromEnvironment("dart.library.html")');
|
|
expectInstance(res, InstanceKind.kBool, true.toString());
|
|
}
|
|
|
|
Future<LibraryRef> getRootLibrary(FlutterTestDriver flutter) async {
|
|
// `isolate.rootLib` returns incorrect library, so find the
|
|
// entrypoint manually here instead.
|
|
//
|
|
// Issue: https://github.com/dart-lang/sdk/issues/44760
|
|
final Isolate isolate = await flutter.getFlutterIsolate();
|
|
return isolate.libraries!
|
|
.firstWhere((LibraryRef l) => l.uri!.contains('org-dartlang-app'));
|
|
}
|
|
|
|
void expectInstance(ObjRef result, String kind, String message) {
|
|
expect(result,
|
|
const TypeMatcher<InstanceRef>()
|
|
.having((InstanceRef instance) => instance.kind, 'kind', kind)
|
|
.having((InstanceRef instance) => instance.valueAsString, 'valueAsString', message));
|
|
}
|
|
|
|
void expectError(ObjRef result, String message) {
|
|
expect(result,
|
|
const TypeMatcher<ErrorRef>()
|
|
.having((ErrorRef instance) => instance.message, 'message', contains(message)));
|
|
}
|