Skip to content

Commit f895e18

Browse files
authored
Integration tests for eval. (#5431)
1 parent 229a147 commit f895e18

File tree

7 files changed

+137
-24
lines changed

7 files changed

+137
-24
lines changed

packages/devtools_app/integration_test/test/live_connection/app_test.dart

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import 'dart:ui' as ui;
66

77
import 'package:devtools_app/devtools_app.dart';
8-
import 'package:devtools_app/src/shared/primitives/simple_items.dart';
98
import 'package:devtools_test/devtools_integration_test.dart';
109
import 'package:flutter/material.dart';
1110
import 'package:flutter_test/flutter_test.dart';
@@ -47,15 +46,10 @@ void main() {
4746
);
4847
expect(tabs.length, equals(availableScreenIds.length));
4948

50-
final screenTitles = (ScreenMetaData.values.toList()
51-
..removeWhere((data) => !availableScreenIds.contains(data.id)))
52-
.map((data) => data.title);
53-
for (final title in screenTitles) {
54-
logStatus('switching to $title screen');
55-
await tester.tap(find.widgetWithText(Tab, title));
56-
// We use pump here instead of pumpAndSettle because pumpAndSettle will
57-
// never complete if there is an animation (e.g. a progress indicator).
58-
await tester.pump(safePumpDuration);
49+
final screens = (ScreenMetaData.values.toList()
50+
..removeWhere((data) => !availableScreenIds.contains(data.id)));
51+
for (final screen in screens) {
52+
await switchToScreen(tester, screen);
5953
}
6054
});
6155
}

packages/devtools_app/integration_test/test/live_connection/eval_and_browse_test.dart

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
import 'dart:ui' as ui;
1010

11+
import 'package:devtools_app/src/shared/console/widgets/console_pane.dart';
1112
import 'package:devtools_app/src/shared/primitives/simple_items.dart';
13+
import 'package:devtools_app/src/shared/ui/search.dart';
1214
import 'package:devtools_test/devtools_integration_test.dart';
13-
import 'package:flutter/material.dart';
15+
import 'package:flutter/services.dart';
1416
import 'package:flutter_test/flutter_test.dart';
1517
import 'package:integration_test/integration_test.dart';
1618

@@ -35,14 +37,85 @@ void main() {
3537
testWidgets('memory eval and browse', (tester) async {
3638
await pumpAndConnectDevTools(tester, testApp);
3739

38-
final screenTitle = ScreenMetaData.memory.title;
40+
final evalTester = _EvalTester(tester);
3941

40-
logStatus('switching to $screenTitle screen');
41-
await tester.tap(find.widgetWithText(Tab, screenTitle));
42-
// We use pump here instead of pumpAndSettle because pumpAndSettle will
43-
// never complete if there is an animation (e.g. a progress indicator).
44-
await tester.pump(safePumpDuration);
42+
await _testBasicEval(evalTester);
43+
await _testAssignment(evalTester);
44+
45+
await switchToScreen(tester, ScreenMetaData.memory);
4546

46-
// TODO(polina-c): add test logic
47+
await _testRootIsAccessible(evalTester);
4748
});
4849
}
50+
51+
Future<void> _testBasicEval(_EvalTester tester) async {
52+
await tester.testEval('21 + 34', '55');
53+
}
54+
55+
Future<void> _testAssignment(_EvalTester tester) async {
56+
await tester.testEval('DateTime(2023)', 'DateTime');
57+
await tester.testEval(
58+
r'var x = $0',
59+
'Variable x is created ',
60+
exact: false,
61+
);
62+
await tester.testEval('x.toString()', "'${DateTime(2023).toString()}'");
63+
}
64+
65+
Future<void> _testRootIsAccessible(_EvalTester tester) async {
66+
// TODO(polina-c): add content.
67+
}
68+
69+
class _EvalTester {
70+
_EvalTester(this.tester);
71+
72+
final WidgetTester tester;
73+
74+
/// Tests if eval returns expected response by searching for response text.
75+
///
76+
/// If [exact] is true, searches for exact match,
77+
/// otherwise for just containment.
78+
Future<void> testEval(
79+
String expression,
80+
String expectedResponse, {
81+
bool exact = true,
82+
}) async {
83+
await tester.tap(find.byType(AutoCompleteSearchField));
84+
await tester.pump(safePumpDuration);
85+
await tester.enterText(find.byType(AutoCompleteSearchField), expression);
86+
await tester.pump(safePumpDuration);
87+
await _pressEnter();
88+
await tester.pump(longPumpDuration);
89+
90+
try {
91+
if (exact) {
92+
expect(
93+
find.widgetWithText(ConsolePane, expectedResponse),
94+
findsOneWidget,
95+
);
96+
} else {
97+
expect(
98+
find.textContaining(expectedResponse),
99+
findsOneWidget,
100+
);
101+
}
102+
} catch (e) {
103+
// In case of unexpected response take golden for troubleshooting.
104+
print('Unexpected response: $e');
105+
await expectLater(
106+
find.byType(ConsolePane),
107+
matchesGoldenFile('eval_and_browse_testEval.png'),
108+
);
109+
}
110+
}
111+
112+
Future<void> _pressEnter() async {
113+
// TODO(polina-c): Figure out why one time sometimes is not enough.
114+
// https://github.com/flutter/devtools/issues/5436
115+
await simulateKeyDownEvent(LogicalKeyboardKey.enter);
116+
await simulateKeyUpEvent(LogicalKeyboardKey.enter);
117+
await tester.pumpAndSettle();
118+
await simulateKeyDownEvent(LogicalKeyboardKey.enter);
119+
await simulateKeyUpEvent(LogicalKeyboardKey.enter);
120+
}
121+
}

packages/devtools_app/integration_test/test/live_connection/performance_screen_event_recording_test.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import 'package:devtools_app/devtools_app.dart';
66
import 'package:devtools_app/src/screens/performance/tabbed_performance_view.dart';
7-
import 'package:devtools_app/src/shared/primitives/simple_items.dart';
87
import 'package:devtools_test/devtools_integration_test.dart';
98
import 'package:flutter/material.dart';
109
import 'package:flutter_test/flutter_test.dart';
@@ -27,10 +26,10 @@ void main() {
2726
logStatus(
2827
'Open the Performance screen and switch to the Timeline Events tab',
2928
);
30-
await tester.tap(
31-
find.widgetWithText(Tab, ScreenMetaData.performance.title),
32-
);
33-
await tester.pump(longPumpDuration);
29+
30+
await switchToScreen(tester, ScreenMetaData.performance);
31+
await tester.pump(safePumpDuration);
32+
3433
await tester.tap(find.widgetWithText(InkWell, 'Timeline Events'));
3534
await tester.pumpAndSettle(longPumpDuration);
3635

packages/devtools_app/lib/devtools_app.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export 'src/shared/notifications.dart';
8383
export 'src/shared/preferences.dart';
8484
export 'src/shared/primitives/auto_dispose.dart';
8585
export 'src/shared/primitives/listenable.dart';
86+
export 'src/shared/primitives/simple_items.dart';
8687
export 'src/shared/primitives/storage.dart';
8788
export 'src/shared/primitives/trace_event.dart';
8889
export 'src/shared/primitives/trees.dart';

packages/devtools_app/lib/src/shared/console/widgets/evaluate.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class ExpressionEvalField extends StatefulWidget {
3838
ExpressionEvalFieldState createState() => ExpressionEvalFieldState();
3939
}
4040

41+
@visibleForTesting
4142
class ExpressionEvalFieldState extends State<ExpressionEvalField>
4243
with AutoDisposeMixin, SearchFieldMixin<ExpressionEvalField> {
4344
static final evalTextFieldKey = GlobalKey(debugLabel: 'evalTextFieldKey');
@@ -445,7 +446,7 @@ class ExpressionEvalFieldState extends State<ExpressionEvalField>
445446

446447
_emitToConsole(
447448
'Variable ${assignment.variableName} is created and now can be used '
448-
'in expression evaluation for the isolate "$isolateName".',
449+
'in expressions for the isolate "$isolateName".',
449450
);
450451

451452
return true;

packages/devtools_app/macos/Runner.xcodeproj/project.pbxproj

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
2828
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
2929
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
30+
38F5D148D47E0A1526658201 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FB6CC413C2B3A116AD9A2ED /* Pods_RunnerTests.framework */; };
3031
E678665441E5C0F7F629BAD5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */; };
3132
/* End PBXBuildFile section */
3233

@@ -78,18 +79,23 @@
7879
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
7980
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
8081
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
82+
371F09A0E3B60E927C1A9DEF /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
8183
5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8284
68C587FFA5A0B8F46A0C5150 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
8385
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
86+
7FB6CC413C2B3A116AD9A2ED /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8487
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
8588
A7CE48BF63861DD9F3A9FA2F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
89+
BA76843FB41FFA4BF4D9F33E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
90+
CDEDCB4DC8BA5A5554F0A2D8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
8691
/* End PBXFileReference section */
8792

8893
/* Begin PBXFrameworksBuildPhase section */
8994
331C80D2294CF70F00263BE5 /* Frameworks */ = {
9095
isa = PBXFrameworksBuildPhase;
9196
buildActionMask = 2147483647;
9297
files = (
98+
38F5D148D47E0A1526658201 /* Pods_RunnerTests.framework in Frameworks */,
9399
);
94100
runOnlyForDeploymentPostprocessing = 0;
95101
};
@@ -185,6 +191,9 @@
185191
11BB555C0F1767B9B5CB7CE0 /* Pods-Runner.debug.xcconfig */,
186192
68C587FFA5A0B8F46A0C5150 /* Pods-Runner.release.xcconfig */,
187193
A7CE48BF63861DD9F3A9FA2F /* Pods-Runner.profile.xcconfig */,
194+
371F09A0E3B60E927C1A9DEF /* Pods-RunnerTests.debug.xcconfig */,
195+
BA76843FB41FFA4BF4D9F33E /* Pods-RunnerTests.release.xcconfig */,
196+
CDEDCB4DC8BA5A5554F0A2D8 /* Pods-RunnerTests.profile.xcconfig */,
188197
);
189198
name = Pods;
190199
path = Pods;
@@ -194,6 +203,7 @@
194203
isa = PBXGroup;
195204
children = (
196205
5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */,
206+
7FB6CC413C2B3A116AD9A2ED /* Pods_RunnerTests.framework */,
197207
);
198208
name = Frameworks;
199209
sourceTree = "<group>";
@@ -205,6 +215,7 @@
205215
isa = PBXNativeTarget;
206216
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
207217
buildPhases = (
218+
02A8F2C8C0022D287A1FCEA5 /* [CP] Check Pods Manifest.lock */,
208219
331C80D1294CF70F00263BE5 /* Sources */,
209220
331C80D2294CF70F00263BE5 /* Frameworks */,
210221
331C80D3294CF70F00263BE5 /* Resources */,
@@ -311,6 +322,28 @@
311322
/* End PBXResourcesBuildPhase section */
312323

313324
/* Begin PBXShellScriptBuildPhase section */
325+
02A8F2C8C0022D287A1FCEA5 /* [CP] Check Pods Manifest.lock */ = {
326+
isa = PBXShellScriptBuildPhase;
327+
buildActionMask = 2147483647;
328+
files = (
329+
);
330+
inputFileListPaths = (
331+
);
332+
inputPaths = (
333+
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
334+
"${PODS_ROOT}/Manifest.lock",
335+
);
336+
name = "[CP] Check Pods Manifest.lock";
337+
outputFileListPaths = (
338+
);
339+
outputPaths = (
340+
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
341+
);
342+
runOnlyForDeploymentPostprocessing = 0;
343+
shellPath = /bin/sh;
344+
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
345+
showEnvVarsInLog = 0;
346+
};
314347
3399D490228B24CF009A79C7 /* ShellScript */ = {
315348
isa = PBXShellScriptBuildPhase;
316349
alwaysOutOfDate = 1;
@@ -439,6 +472,7 @@
439472
/* Begin XCBuildConfiguration section */
440473
331C80DB294CF71000263BE5 /* Debug */ = {
441474
isa = XCBuildConfiguration;
475+
baseConfigurationReference = 371F09A0E3B60E927C1A9DEF /* Pods-RunnerTests.debug.xcconfig */;
442476
buildSettings = {
443477
BUNDLE_LOADER = "$(TEST_HOST)";
444478
CURRENT_PROJECT_VERSION = 1;
@@ -453,6 +487,7 @@
453487
};
454488
331C80DC294CF71000263BE5 /* Release */ = {
455489
isa = XCBuildConfiguration;
490+
baseConfigurationReference = BA76843FB41FFA4BF4D9F33E /* Pods-RunnerTests.release.xcconfig */;
456491
buildSettings = {
457492
BUNDLE_LOADER = "$(TEST_HOST)";
458493
CURRENT_PROJECT_VERSION = 1;
@@ -467,6 +502,7 @@
467502
};
468503
331C80DD294CF71000263BE5 /* Profile */ = {
469504
isa = XCBuildConfiguration;
505+
baseConfigurationReference = CDEDCB4DC8BA5A5554F0A2D8 /* Pods-RunnerTests.profile.xcconfig */;
470506
buildSettings = {
471507
BUNDLE_LOADER = "$(TEST_HOST)";
472508
CURRENT_PROJECT_VERSION = 1;

packages/devtools_test/lib/src/integration_test/integration_test_utils.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ Future<void> pumpAndConnectDevTools(
4141
}
4242
}
4343

44+
Future<void> switchToScreen(WidgetTester tester, ScreenMetaData screen) async {
45+
final screenTitle = screen.title;
46+
logStatus('switching to $screenTitle screen');
47+
await tester.tap(find.widgetWithText(Tab, screenTitle));
48+
// We use pump here instead of pumpAndSettle because pumpAndSettle will
49+
// never complete if there is an animation (e.g. a progress indicator).
50+
await tester.pump(safePumpDuration);
51+
}
52+
4453
Future<void> pumpDevTools(WidgetTester tester) async {
4554
// TODO(kenz): how can we share code across integration_test/test and
4655
// integration_test/test_infra? When trying to import, we get an error:

0 commit comments

Comments
 (0)