blob: 4a393a8e7289dd5b788733c57e20a35392c48d51 [file]
// Copyright 2019 The Chromium 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:devtools_app/src/analytics/stub_provider.dart';
import 'package:devtools_app/src/debugger/debugger_screen.dart';
import 'package:devtools_app/src/framework_controller.dart';
import 'package:devtools_app/src/globals.dart';
import 'package:devtools_app/src/scaffold.dart';
import 'package:devtools_app/src/screen.dart';
import 'package:devtools_app/src/service_manager.dart';
import 'package:devtools_app/src/survey.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'support/mocks.dart';
import 'support/wrappers.dart';
void main() {
group('DevToolsScaffold widget', () {
MockServiceManager mockServiceManager;
setUp(() {
mockServiceManager = MockServiceManager();
when(mockServiceManager.service).thenReturn(null);
when(mockServiceManager.hasConnection).thenReturn(false);
when(mockServiceManager.connectedState).thenReturn(
ValueNotifier<ConnectedState>(const ConnectedState(false)));
final mockErrorBadgeManager = MockErrorBadgeManager();
when(mockServiceManager.errorBadgeManager)
.thenReturn(mockErrorBadgeManager);
when(mockErrorBadgeManager.errorCountNotifier(any))
.thenReturn(ValueNotifier<int>(0));
setGlobal(ServiceConnectionManager, mockServiceManager);
setGlobal(FrameworkController, FrameworkController());
setGlobal(SurveyService, SurveyService());
});
testWidgetsWithWindowSize(
'displays in narrow mode without error', const Size(200.0, 1200.0),
(WidgetTester tester) async {
await tester.pumpWidget(wrap(
DevToolsScaffold(
tabs: const [screen1, screen2, screen3, screen4, screen5],
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
));
expect(find.byKey(k1), findsOneWidget);
expect(find.byKey(DevToolsScaffold.narrowWidthKey), findsOneWidget);
expect(find.byKey(DevToolsScaffold.fullWidthKey), findsNothing);
});
testWidgetsWithWindowSize(
'displays in full-width mode without error', const Size(1200.0, 1200.0),
(WidgetTester tester) async {
await tester.pumpWidget(wrap(
DevToolsScaffold(
tabs: const [screen1, screen2, screen3, screen4, screen5],
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
));
expect(find.byKey(k1), findsOneWidget);
expect(find.byKey(DevToolsScaffold.fullWidthKey), findsOneWidget);
expect(find.byKey(DevToolsScaffold.narrowWidthKey), findsNothing);
});
testWidgets('displays no tabs when only one is given',
(WidgetTester tester) async {
await tester.pumpWidget(wrap(
DevToolsScaffold(
tabs: const [screen1],
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
));
expect(find.byKey(k1), findsOneWidget);
expect(find.byKey(t1), findsNothing);
});
testWidgets('displays only the selected tab', (WidgetTester tester) async {
await tester.pumpWidget(wrap(
DevToolsScaffold(
tabs: const [screen1, screen2],
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
));
expect(find.byKey(k1), findsOneWidget);
expect(find.byKey(k2), findsNothing);
// Tap on the tab for screen 2, then let the animation finish before
// checking the body is updated.
await tester.tap(find.byKey(t2));
await tester.pumpAndSettle();
expect(find.byKey(k1), findsNothing);
expect(find.byKey(k2), findsOneWidget);
// Return to screen 1.
await tester.tap(find.byKey(t1));
await tester.pumpAndSettle();
expect(find.byKey(k1), findsOneWidget);
expect(find.byKey(k2), findsNothing);
});
testWidgets('displays the requested initial page',
(WidgetTester tester) async {
await tester.pumpWidget(wrap(
DevToolsScaffold(
tabs: const [screen1, screen2],
page: screen2.screenId,
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
));
expect(find.byKey(k1), findsNothing);
expect(find.byKey(k2), findsOneWidget);
});
testWidgets('displays floating debugger controls',
(WidgetTester tester) async {
final mockConnectedApp = MockConnectedApp();
when(mockConnectedApp.isFlutterAppNow).thenReturn(true);
when(mockServiceManager.hasConnection).thenReturn(true);
when(mockServiceManager.connectedApp).thenReturn(mockConnectedApp);
final mockDebuggerController = MockDebuggerController();
when(mockDebuggerController.isPaused)
.thenReturn(ValueNotifier<bool>(false));
await tester.pumpWidget(wrapWithControllers(
DevToolsScaffold(
tabs: const [screen1, screen2],
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
debugger: mockDebuggerController,
));
expect(find.byKey(k1), findsOneWidget);
expect(find.byKey(k2), findsNothing);
expect(find.byType(FloatingDebuggerControls), findsOneWidget);
});
testWidgets(
'does not display floating debugger controls when debugger screen is showing',
(WidgetTester tester) async {
final mockConnectedApp = MockConnectedApp();
when(mockConnectedApp.isFlutterAppNow).thenReturn(true);
when(mockServiceManager.hasConnection).thenReturn(true);
when(mockServiceManager.connectedApp).thenReturn(mockConnectedApp);
final mockDebuggerController = MockDebuggerController();
when(mockDebuggerController.isPaused)
.thenReturn(ValueNotifier<bool>(false));
const debuggerScreenKey = Key('debugger screen');
const debuggerTabKey = Key('debugger tab');
await tester.pumpWidget(wrapWithControllers(
DevToolsScaffold(
tabs: const [
_TestScreen(
DebuggerScreen.id,
debuggerScreenKey,
tabKey: debuggerTabKey,
),
screen2,
],
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
debugger: mockDebuggerController,
));
expect(find.byKey(debuggerScreenKey), findsOneWidget);
expect(find.byKey(k2), findsNothing);
expect(find.byType(FloatingDebuggerControls), findsNothing);
// Tap on the tab for screen 2 and verify the controls are present.
await tester.tap(find.byKey(t2));
await tester.pumpAndSettle();
await tester.pumpAndSettle();
expect(find.byKey(debuggerScreenKey), findsNothing);
expect(find.byKey(k2), findsOneWidget);
expect(find.byType(FloatingDebuggerControls), findsOneWidget);
// Return to the debugger screen and verify the controls are gone.
await tester.tap(find.byKey(debuggerTabKey));
await tester.pumpAndSettle();
await tester.pumpAndSettle();
expect(find.byKey(debuggerScreenKey), findsOneWidget);
expect(find.byKey(k2), findsNothing);
expect(find.byType(FloatingDebuggerControls), findsNothing);
});
testWidgets(
'does not display floating debugger tab controls when no app is connected',
(WidgetTester tester) async {
when(mockServiceManager.hasConnection).thenReturn(false);
await tester.pumpWidget(wrap(
DevToolsScaffold(
tabs: const [screen1, screen2],
ideTheme: null,
analyticsProvider: await analyticsProvider,
),
));
expect(find.byKey(k1), findsOneWidget);
expect(find.byKey(k2), findsNothing);
expect(find.byType(FloatingDebuggerControls), findsNothing);
});
});
}
class _TestScreen extends Screen {
const _TestScreen(this.name, this.key, {Key tabKey})
: super(
name,
title: name,
icon: Icons.computer,
tabKey: tabKey,
);
final String name;
final Key key;
@override
Widget build(BuildContext context) {
return SizedBox(key: key);
}
}
// Keys and tabs for use in the test.
const k1 = Key('body key 1');
const k2 = Key('body key 2');
const k3 = Key('body key 3');
const k4 = Key('body key 4');
const k5 = Key('body key 5');
const t1 = Key('tab key 1');
const t2 = Key('tab key 2');
const message1Key = Key('test message 1');
const message2Key = Key('test message 2');
const screen1 = _TestScreen('screen1', k1, tabKey: t1);
const screen2 = _TestScreen('screen2', k2, tabKey: t2);
const screen3 = _TestScreen('screen3', k3);
const screen4 = _TestScreen('screen4', k4);
const screen5 = _TestScreen('screen5', k5);