blob: c2cf6d6dab1b730333c7a5e93769a66cce28c6f6 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
@TestOn('vm')
import 'package:dwds/src/connections/debug_connection.dart';
import 'package:dwds/src/debugging/debugger.dart';
import 'package:dwds/src/debugging/inspector.dart';
import 'package:dwds/src/loaders/strategy.dart';
import 'package:dwds/src/utilities/conversions.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
import 'fixtures/context.dart';
final context = TestContext(
directory: '../example', path: 'scopes.html', pathToServe: 'web');
WipConnection get tabConnection => context.tabConnection;
void main() {
AppInspector inspector;
Debugger debugger;
setUpAll(() async {
await context.setUp();
var service = fetchChromeProxyService(context.debugConnection);
inspector = service.appInspectorProvider();
debugger = inspector.debugger;
});
tearDownAll(() async {
await context.tearDown();
});
final url = 'org-dartlang-app:///web/scopes_main.dart';
/// A convenient way to get a library variable without boilerplate.
String libraryVariableExpression(String variable) =>
'${globalLoadStrategy.loadModuleSnippet}("dart_sdk").dart.getModuleLibraries("web/scopes_main")["$url"]["$variable"];';
Future<RemoteObject> libraryPublicFinal() =>
inspector.jsEvaluate(libraryVariableExpression('libraryPublicFinal'));
test('send toString', () async {
var remoteObject = await libraryPublicFinal();
var toString = await inspector.invokeMethod(remoteObject, 'toString', []);
expect(toString.value, 'A test class with message world');
});
group('getObject', () {
test('for class with generic', () async {
var isolateId = inspector.isolate.id;
var remoteObject = await libraryPublicFinal();
var instance = await inspector.getObject(isolateId, remoteObject.objectId)
as Instance;
var classRef = instance.classRef;
var clazz = await inspector.getObject(isolateId, classRef.id) as Class;
expect(clazz.name, 'MyTestClass<dynamic>');
});
});
group('loadField', () {
test('for string', () async {
var remoteObject = await libraryPublicFinal();
var message = await inspector.loadField(remoteObject, 'message');
expect(message.value, 'world');
});
test('for num', () async {
var remoteObject = await libraryPublicFinal();
var count = await inspector.loadField(remoteObject, 'count');
expect(count.value, 0);
});
});
test('properties', () async {
var remoteObject = await libraryPublicFinal();
var properties = await debugger.getProperties(remoteObject.objectId);
var names =
properties.map((p) => p.name).where((x) => x != '__proto__').toList();
var expected = [
'_privateField',
'abstractField',
'closure',
'count',
'message',
'myselfField',
'notFinal',
'tornOff',
];
names.sort();
expect(names, expected);
});
group('invoke', () {
// We test these here because the test fixture has more complicated members
// to exercise.
String isolateId;
LibraryRef bootstrapLibrary;
RemoteObject instance;
setUp(() async {
isolateId = inspector.isolate.id;
bootstrapLibrary = inspector.isolate.rootLib;
instance = await inspector.evaluate(
isolateId, bootstrapLibrary.id, 'libraryPublicFinal');
});
test('invoke top-level private', () async {
var remote = await inspector.invoke(isolateId, bootstrapLibrary.id,
'_libraryPrivateFunction', [dartIdFor(2), dartIdFor(3)]);
expect(
remote,
const TypeMatcher<RemoteObject>()
.having((instance) => instance.value, 'result', 5));
});
test('invoke instance private', () async {
var remote = await inspector.invoke(isolateId, instance.objectId,
'privateMethod', [dartIdFor('some string')]);
expect(
remote,
const TypeMatcher<RemoteObject>().having((instance) => instance.value,
'result', 'some string : a private field'));
});
test('invoke instance method with object parameter', () async {
var remote = await inspector
.invoke(isolateId, instance.objectId, 'equals', [instance.objectId]);
expect(
remote,
const TypeMatcher<RemoteObject>()
.having((instance) => instance.value, 'result', true));
});
test('invoke instance method with object parameter 2', () async {
var libraryPrivateList = await inspector.evaluate(
isolateId, bootstrapLibrary.id, '_libraryPrivate');
var remote = await inspector.invoke(isolateId, instance.objectId,
'equals', [libraryPrivateList.objectId]);
expect(
remote,
const TypeMatcher<RemoteObject>()
.having((instance) => instance.value, 'result', false));
});
test('invoke closure stored in an instance field', () async {
var remote =
await inspector.invoke(isolateId, instance.objectId, 'closure', []);
expect(
remote,
const TypeMatcher<RemoteObject>()
.having((instance) => instance.value, 'result', null));
});
test('invoke a torn-off method', () async {
var toString = await inspector.loadField(instance, 'tornOff');
var result =
await inspector.invoke(isolateId, toString.objectId, 'call', []);
expect(
result,
const TypeMatcher<RemoteObject>().having((instance) => instance.value,
'toString', 'A test class with message world'));
});
});
}