[web] Remove HTML renderer from framework tests (#162038)
- Cleanup many HTML special cases and skips in framework tests. - Update some dartdocs that referred to the HTML renderer. For reviewers: it may help if you set `Hide whitespace` to true in Github. It will help you skip through all the formatting/indentation changes.
This commit is contained in:
parent
b82e9022a3
commit
3755fd1f6e
@ -22,9 +22,6 @@ import 'material.dart';
|
||||
/// Begin a Material 3 ink sparkle ripple, centered at the tap or click position
|
||||
/// relative to the [referenceBox].
|
||||
///
|
||||
/// This effect relies on a shader and therefore is unsupported on the Flutter
|
||||
/// Web HTML backend.
|
||||
///
|
||||
/// To use this effect, pass an instance of [splashFactory] to the
|
||||
/// `splashFactory` parameter of either the Material [ThemeData] or any
|
||||
/// component that has a `splashFactory` parameter, such as buttons:
|
||||
|
@ -335,9 +335,8 @@ class _ZoomEnterTransition extends StatefulWidget {
|
||||
|
||||
class _ZoomEnterTransitionState extends State<_ZoomEnterTransition>
|
||||
with _ZoomTransitionBase<_ZoomEnterTransition> {
|
||||
// See SnapshotWidget doc comment, this is disabled on web because the HTML backend doesn't
|
||||
// support this functionality and the canvaskit backend uses a single thread for UI and raster
|
||||
// work which diminishes the impact of this performance improvement.
|
||||
// See SnapshotWidget doc comment, this is disabled on web because the canvaskit backend uses a
|
||||
// single thread for UI and raster work which diminishes the impact of this performance improvement.
|
||||
@override
|
||||
bool get useSnapshot => !kIsWeb && widget.allowSnapshotting;
|
||||
|
||||
@ -447,9 +446,8 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition>
|
||||
with _ZoomTransitionBase<_ZoomExitTransition> {
|
||||
late _ZoomExitTransitionPainter delegate;
|
||||
|
||||
// See SnapshotWidget doc comment, this is disabled on web because the HTML backend doesn't
|
||||
// support this functionality and the canvaskit backend uses a single thread for UI and raster
|
||||
// work which diminishes the impact of this performance improvement.
|
||||
// See SnapshotWidget doc comment, this is disabled on web because the canvaskit backend uses a
|
||||
// single thread for UI and raster work which diminishes the impact of this performance improvement.
|
||||
@override
|
||||
bool get useSnapshot => !kIsWeb && widget.allowSnapshotting;
|
||||
|
||||
|
@ -99,11 +99,8 @@ class SnapshotController extends ChangeNotifier {
|
||||
/// defaults to [SnapshotMode.normal] which will throw an exception if a
|
||||
/// platform view is encountered.
|
||||
///
|
||||
/// * The snapshotting functionality of this widget is not supported on the HTML
|
||||
/// backend of Flutter for the Web. Setting [SnapshotController.allowSnapshotting] to true
|
||||
/// may cause an error to be thrown. On the CanvasKit backend of Flutter, the
|
||||
/// performance of using this widget may regress performance due to the fact
|
||||
/// that both the UI and engine share a single thread.
|
||||
/// * On the CanvasKit backend of Flutter, the performance of using this widget may regress
|
||||
/// performance due to the fact that both the UI and engine share a single thread.
|
||||
class SnapshotWidget extends SingleChildRenderObjectWidget {
|
||||
/// Create a new [SnapshotWidget].
|
||||
///
|
||||
|
@ -12,7 +12,7 @@ import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart' show isCanvasKit;
|
||||
import 'package:flutter/foundation.dart' show isSkwasm;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -20,7 +20,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import '../impeller_test_helpers.dart';
|
||||
|
||||
// TODO(yjbanov): on the web text rendered with perspective produces flaky goldens: https://github.com/flutter/flutter/issues/110785
|
||||
final bool skipPerspectiveTextGoldens = isBrowser && !isCanvasKit;
|
||||
final bool skipPerspectiveTextGoldens = isBrowser && isSkwasm;
|
||||
|
||||
// A number of the hit tests below say "warnIfMissed: false". This is because
|
||||
// the way the CupertinoPicker works, the hits don't actually reach the labels,
|
||||
|
@ -928,10 +928,7 @@ void main() {
|
||||
// regular font. However, when using the test font, "Cancel" becomes 2 lines which
|
||||
// is why the height we're verifying for "Cancel" is larger than "OK".
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(tester.getSize(find.text('The Title')), equals(const Size(270.0, 132.0)));
|
||||
}
|
||||
expect(tester.getSize(find.text('The Title')), equals(const Size(270.0, 132.0)));
|
||||
expect(tester.getTopLeft(find.text('The Title')), equals(const Offset(265.0, 80.0 + 24.0)));
|
||||
expect(
|
||||
tester.getSize(find.widgetWithText(CupertinoDialogAction, 'Cancel')),
|
||||
|
@ -109,50 +109,45 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets(
|
||||
'chevrons point to the correct side',
|
||||
(WidgetTester tester) async {
|
||||
// Add enough TestBoxes to need 3 pages.
|
||||
final List<Widget> children = List<Widget>.generate(15, (int i) => const TestBox());
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: Center(
|
||||
child: CupertinoTextSelectionToolbar(
|
||||
anchorAbove: const Offset(50.0, 100.0),
|
||||
anchorBelow: const Offset(50.0, 200.0),
|
||||
children: children,
|
||||
),
|
||||
testWidgets('chevrons point to the correct side', (WidgetTester tester) async {
|
||||
// Add enough TestBoxes to need 3 pages.
|
||||
final List<Widget> children = List<Widget>.generate(15, (int i) => const TestBox());
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: Center(
|
||||
child: CupertinoTextSelectionToolbar(
|
||||
anchorAbove: const Offset(50.0, 100.0),
|
||||
anchorBelow: const Offset(50.0, 200.0),
|
||||
children: children,
|
||||
),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
expect(findOverflowBackButton(), findsNothing);
|
||||
expect(findOverflowNextButton(), findsOneWidget);
|
||||
expect(findOverflowBackButton(), findsNothing);
|
||||
expect(findOverflowNextButton(), findsOneWidget);
|
||||
|
||||
expect(findOverflowNextButton(), overflowNextPaintPattern());
|
||||
expect(findOverflowNextButton(), overflowNextPaintPattern());
|
||||
|
||||
// Tap the overflow next button to show the next page of children.
|
||||
await tester.tapAt(tester.getCenter(findOverflowNextButton()));
|
||||
await tester.pumpAndSettle();
|
||||
// Tap the overflow next button to show the next page of children.
|
||||
await tester.tapAt(tester.getCenter(findOverflowNextButton()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(findOverflowBackButton(), findsOneWidget);
|
||||
expect(findOverflowNextButton(), findsOneWidget);
|
||||
expect(findOverflowBackButton(), findsOneWidget);
|
||||
expect(findOverflowNextButton(), findsOneWidget);
|
||||
|
||||
expect(findOverflowBackButton(), overflowBackPaintPattern());
|
||||
expect(findOverflowNextButton(), overflowNextPaintPattern());
|
||||
expect(findOverflowBackButton(), overflowBackPaintPattern());
|
||||
expect(findOverflowNextButton(), overflowNextPaintPattern());
|
||||
|
||||
// Tap the overflow next button to show the last page of children.
|
||||
await tester.tapAt(tester.getCenter(findOverflowNextButton()));
|
||||
await tester.pumpAndSettle();
|
||||
// Tap the overflow next button to show the last page of children.
|
||||
await tester.tapAt(tester.getCenter(findOverflowNextButton()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(findOverflowBackButton(), findsOneWidget);
|
||||
expect(findOverflowNextButton(), findsNothing);
|
||||
expect(findOverflowBackButton(), findsOneWidget);
|
||||
expect(findOverflowNextButton(), findsNothing);
|
||||
|
||||
expect(findOverflowBackButton(), overflowBackPaintPattern());
|
||||
},
|
||||
// Path.combine is not implemented in the HTML backend https://github.com/flutter/flutter/issues/44572
|
||||
skip: kIsWeb,
|
||||
);
|
||||
expect(findOverflowBackButton(), overflowBackPaintPattern());
|
||||
});
|
||||
|
||||
testWidgets('paginates children if they overflow', (WidgetTester tester) async {
|
||||
late StateSetter setState;
|
||||
|
@ -479,7 +479,7 @@ void main() {
|
||||
tester.getTopLeft(find.text('Licenses')),
|
||||
const Offset(16.0 + safeareaPadding, 14.0 + safeareaPadding),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('LicensePage returns early if unmounted', (WidgetTester tester) async {
|
||||
final Completer<LicenseEntry> licenseCompleter = Completer<LicenseEntry>();
|
||||
@ -1464,10 +1464,7 @@ void main() {
|
||||
// If the layout width is less than 840.0 pixels, nested layout is
|
||||
// used which positions license page title at the top center.
|
||||
Offset titleOffset = tester.getCenter(find.text(title));
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(titleOffset, Offset(defaultSize.width / 2, 96.0));
|
||||
}
|
||||
expect(titleOffset, Offset(defaultSize.width / 2, 96.0));
|
||||
expect(tester.getCenter(find.byType(ListView)), Offset(defaultSize.width / 2, 328.0));
|
||||
|
||||
// Configure a wide window to show the lateral UI.
|
||||
@ -1588,10 +1585,7 @@ void main() {
|
||||
// If the layout width is less than 840.0 pixels, nested layout is
|
||||
// used which positions license page title at the top center.
|
||||
Offset titleOffset = tester.getCenter(find.text(title));
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(titleOffset, Offset(defaultSize.width / 2, 96.0));
|
||||
}
|
||||
expect(titleOffset, Offset(defaultSize.width / 2, 96.0));
|
||||
expect(tester.getCenter(find.byType(ListView)), Offset(defaultSize.width / 2, 328.0));
|
||||
|
||||
// Configure a wide window to show the lateral UI.
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -241,7 +240,7 @@ void main() {
|
||||
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
|
||||
expect(tester.getRect(expandedTitle).height, 43.0);
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.large expanded title has upper limit on text scaling', (
|
||||
WidgetTester tester,
|
||||
@ -275,46 +274,44 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
|
||||
expect(tester.getRect(expandedTitle).height, closeTo(48.0, 0.1));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'SliverAppBar.medium expanded title position is adjusted with textScaleFactor',
|
||||
(WidgetTester tester) async {
|
||||
const String title = 'Medium AppBar';
|
||||
Widget buildAppBar({double textScaleFactor = 1.0}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(useMaterial3: true),
|
||||
home: MediaQuery.withClampedTextScaling(
|
||||
minScaleFactor: textScaleFactor,
|
||||
maxScaleFactor: textScaleFactor,
|
||||
child: Material(
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
const SliverAppBar.medium(title: Text(title, maxLines: 1)),
|
||||
SliverToBoxAdapter(child: Container(height: 1200, color: Colors.orange[400])),
|
||||
],
|
||||
),
|
||||
testWidgets('SliverAppBar.medium expanded title position is adjusted with textScaleFactor', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const String title = 'Medium AppBar';
|
||||
Widget buildAppBar({double textScaleFactor = 1.0}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(useMaterial3: true),
|
||||
home: MediaQuery.withClampedTextScaling(
|
||||
minScaleFactor: textScaleFactor,
|
||||
maxScaleFactor: textScaleFactor,
|
||||
child: Material(
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
const SliverAppBar.medium(title: Text(title, maxLines: 1)),
|
||||
SliverToBoxAdapter(child: Container(height: 1200, color: Colors.orange[400])),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildAppBar());
|
||||
await tester.pumpWidget(buildAppBar());
|
||||
|
||||
final Finder expandedTitle = find.text(title).first;
|
||||
expect(tester.getBottomLeft(expandedTitle).dy, 96.0);
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
final Finder expandedTitle = find.text(title).first;
|
||||
expect(tester.getBottomLeft(expandedTitle).dy, 96.0);
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
|
||||
await tester.pumpWidget(buildAppBar(textScaleFactor: 2.0));
|
||||
expect(tester.getBottomLeft(expandedTitle).dy, 107.0);
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
await tester.pumpWidget(buildAppBar(textScaleFactor: 2.0));
|
||||
expect(tester.getBottomLeft(expandedTitle).dy, 107.0);
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
|
||||
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
|
||||
expect(tester.getBottomLeft(expandedTitle).dy, 107.0);
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
|
||||
expect(tester.getBottomLeft(expandedTitle).dy, 107.0);
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar.large expanded title position is adjusted with textScaleFactor', (
|
||||
WidgetTester tester,
|
||||
@ -1264,9 +1261,7 @@ void main() {
|
||||
// Test the expanded title is positioned correctly.
|
||||
final Offset titleOffset = tester.getBottomLeft(expandedTitle);
|
||||
expect(titleOffset.dx, 16.0);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
expect(titleOffset.dy, 96.0);
|
||||
}
|
||||
expect(titleOffset.dy, 96.0);
|
||||
|
||||
verifyTextNotClipped(expandedTitle, tester);
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -42,10 +41,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size
|
||||
expect(tester.getTopLeft(find.byType(Badge)), Offset.zero);
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(tester.getTopLeft(find.text('0')), const Offset(16, -4));
|
||||
}
|
||||
expect(tester.getTopLeft(find.text('0')), const Offset(16, -4));
|
||||
|
||||
final RenderBox box = tester.renderObject(find.byType(Badge));
|
||||
final RRect rrect = RRect.fromLTRBR(12, -4, 31.5, 12, const Radius.circular(8));
|
||||
@ -82,10 +78,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size
|
||||
expect(tester.getTopLeft(find.byType(Badge)), Offset.zero);
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(tester.getTopLeft(find.text('0')), const Offset(0, -4));
|
||||
}
|
||||
expect(tester.getTopLeft(find.text('0')), const Offset(0, -4));
|
||||
|
||||
final RenderBox box = tester.renderObject(find.byType(Badge));
|
||||
final RRect rrect = RRect.fromLTRBR(-4, -4, 15.5, 12, const Radius.circular(8));
|
||||
@ -132,10 +125,7 @@ void main() {
|
||||
|
||||
// x = alignment.start + padding.left
|
||||
// y = alignment.top
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(tester.getTopLeft(find.text('0')), const Offset(16, -4));
|
||||
}
|
||||
expect(tester.getTopLeft(find.text('0')), const Offset(16, -4));
|
||||
|
||||
final RenderBox box = tester.renderObject(find.byType(Badge));
|
||||
// '0'.width = 12
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -258,29 +257,17 @@ void main() {
|
||||
await tester.pumpWidget(buildApp(textScaler: TextScaler.noScaling));
|
||||
expect(find.text(label), findsOneWidget);
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(tester.getSize(find.text(label)), const Size(14.25, 20.0));
|
||||
}
|
||||
expect(tester.getSize(find.text(label)), const Size(14.25, 20.0));
|
||||
|
||||
await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(1.1)));
|
||||
await tester.pumpAndSettle();
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(15.65, 22.0)), true);
|
||||
}
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(15.65, 22.0)), true);
|
||||
|
||||
await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(1.5)));
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(21.25, 30)), true);
|
||||
}
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(21.25, 30)), true);
|
||||
|
||||
await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(4)));
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(21.25, 30)), true);
|
||||
}
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(21.25, 30)), true);
|
||||
});
|
||||
|
||||
group('MaterialBanner elevation', () {
|
||||
|
@ -10,7 +10,6 @@ library;
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -1687,7 +1686,6 @@ void main() {
|
||||
await tester.longPress(find.text(label));
|
||||
expect(tester.getSize(find.text(label).last).height, equals(80.0));
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
|
||||
testWidgets('Different behaviour of tool tip in BottomNavigationBarItem', (
|
||||
@ -2711,7 +2709,7 @@ void main() {
|
||||
tester.getRect(find.byKey(icon1)),
|
||||
Rect.fromLTRB(500.0, iconTop, 700.0, iconTop + iconHeight),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - BottomNavigationBar centered landscape layout', (
|
||||
WidgetTester tester,
|
||||
@ -2855,7 +2853,7 @@ void main() {
|
||||
tester.getRect(find.byKey(icon1)),
|
||||
Rect.fromLTRB(450.0, iconTop, 650.0, iconTop + iconHeight),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - BottomNavigationBar linear landscape layout', (
|
||||
WidgetTester tester,
|
||||
@ -2995,7 +2993,7 @@ void main() {
|
||||
tester.getRect(find.byKey(icon1)),
|
||||
Rect.fromLTRB(secondItemLeft, iconTop, secondItemLeft + iconWidth, iconTop + iconHeight),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('BottomNavigationBar linear landscape layout label RenderFlex overflow', (
|
||||
WidgetTester tester,
|
||||
|
@ -521,7 +521,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Text)).width, closeTo(40.4, 0.01));
|
||||
expect(tester.getSize(find.byType(Text)).height, equals(14.0));
|
||||
expect(tester.getSize(find.byType(Chip)), const Size(800.0, 48.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Chip responds to materialTapTargetSize', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
@ -555,7 +555,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Chip).first).height, equals(48.0));
|
||||
expect(tester.getSize(find.byType(Chip).last).width, closeTo(48.1, 0.01));
|
||||
expect(tester.getSize(find.byType(Chip).last).height, equals(38.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Delete button tap target is the right proportion of the chip', (
|
||||
WidgetTester tester,
|
||||
@ -779,7 +779,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Chip).first).height, equals(78.0));
|
||||
expect(tester.getSize(find.byType(Chip).last).width, closeTo(138.59, 0.01));
|
||||
expect(tester.getSize(find.byType(Chip).last).height, equals(48.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Labels can be non-text widgets', (WidgetTester tester) async {
|
||||
final Key keyA = GlobalKey();
|
||||
@ -828,7 +828,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(Chip).first).width, moreOrLessEquals(138.5, epsilon: 0.1));
|
||||
expect(tester.getSize(find.byType(Chip).first).height, equals(48.0));
|
||||
expect(tester.getSize(find.byType(Chip).last), const Size(60.0, 48.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Avatars can be non-circle avatar widgets', (WidgetTester tester) async {
|
||||
final Key keyA = GlobalKey();
|
||||
@ -1188,7 +1188,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(RawChip)).height, equals(48.0));
|
||||
expect(tester.getTopLeft(find.byKey(labelKey)), equals(const Offset(17.0, 14.0)));
|
||||
expect(find.byKey(avatarKey), findsNothing);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Delete button drawer works as expected on RawChip', (
|
||||
WidgetTester tester,
|
||||
@ -1455,7 +1455,7 @@ void main() {
|
||||
expect(tester.getSize(find.byType(RawChip)).height, equals(48.0));
|
||||
expect(tester.getTopLeft(find.byKey(labelKey)), equals(const Offset(17.0, 14.0)));
|
||||
expect(find.byKey(deleteButtonKey), findsNothing);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Delete button takes up at most half of the chip', (WidgetTester tester) async {
|
||||
final UniqueKey chipKey = UniqueKey();
|
||||
@ -2140,7 +2140,7 @@ void main() {
|
||||
// Simulate a tap on the label to select the chip.
|
||||
await tester.tap(find.byKey(labelKey));
|
||||
expect(selected, equals(true));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb && isSkiaWeb ? 3 : 1));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb ? 3 : 1));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
expect(getSelectProgress(tester), moreOrLessEquals(0.002, epsilon: 0.01));
|
||||
@ -2159,7 +2159,7 @@ void main() {
|
||||
// Simulate another tap on the label to deselect the chip.
|
||||
await tester.tap(find.byKey(labelKey));
|
||||
expect(selected, equals(false));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb && isSkiaWeb ? 3 : 1));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb ? 3 : 1));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 20));
|
||||
expect(getSelectProgress(tester), moreOrLessEquals(0.875, epsilon: 0.01));
|
||||
@ -2173,7 +2173,7 @@ void main() {
|
||||
expect(getSelectProgress(tester), equals(0.0));
|
||||
expect(getAvatarDrawerProgress(tester), equals(1.0));
|
||||
expect(getDeleteDrawerProgress(tester), equals(0.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Selection without avatar works as expected on RawChip', (
|
||||
WidgetTester tester,
|
||||
@ -2302,7 +2302,7 @@ void main() {
|
||||
// Simulate a tap on the label to select the chip.
|
||||
await tester.tap(find.byKey(labelKey));
|
||||
expect(selected, equals(true));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb && isSkiaWeb ? 3 : 1));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb ? 3 : 1));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
expect(getSelectProgress(tester), moreOrLessEquals(0.002, epsilon: 0.01));
|
||||
@ -2322,7 +2322,7 @@ void main() {
|
||||
// Simulate another tap on the label to deselect the chip.
|
||||
await tester.tap(find.byKey(labelKey));
|
||||
expect(selected, equals(false));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb && isSkiaWeb ? 3 : 1));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb ? 3 : 1));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 20));
|
||||
expect(getSelectProgress(tester), moreOrLessEquals(0.875, epsilon: 0.01));
|
||||
@ -2336,7 +2336,7 @@ void main() {
|
||||
expect(getSelectProgress(tester), equals(0.0));
|
||||
expect(getAvatarDrawerProgress(tester), equals(0.0));
|
||||
expect(getDeleteDrawerProgress(tester), equals(0.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Activation works as expected on RawChip', (WidgetTester tester) async {
|
||||
bool selected = false;
|
||||
@ -2436,7 +2436,7 @@ void main() {
|
||||
|
||||
await tester.tap(find.byKey(labelKey));
|
||||
expect(selected, equals(true));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb && isSkiaWeb ? 3 : 1));
|
||||
expect(SchedulerBinding.instance.transientCallbackCount, equals(kIsWeb ? 3 : 1));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
expect(getSelectProgress(tester), moreOrLessEquals(0.002, epsilon: 0.01));
|
||||
@ -2451,7 +2451,7 @@ void main() {
|
||||
expect(getAvatarDrawerProgress(tester), equals(1.0));
|
||||
expect(getDeleteDrawerProgress(tester), equals(0.0));
|
||||
await tester.pumpAndSettle();
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Chip uses ThemeData chip theme if present', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(
|
||||
@ -2576,37 +2576,35 @@ void main() {
|
||||
expect(tester.getSize(find.byKey(key2)), const Size(80.0, 32.0));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Material3 - Chip size is configurable by ThemeData.materialTapTargetSize',
|
||||
(WidgetTester tester) async {
|
||||
final Key key1 = UniqueKey();
|
||||
await tester.pumpWidget(
|
||||
wrapForChip(
|
||||
child: Theme(
|
||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.padded),
|
||||
child: Center(child: RawChip(key: key1, label: const Text('test'))),
|
||||
),
|
||||
testWidgets('Material3 - Chip size is configurable by ThemeData.materialTapTargetSize', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final Key key1 = UniqueKey();
|
||||
await tester.pumpWidget(
|
||||
wrapForChip(
|
||||
child: Theme(
|
||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.padded),
|
||||
child: Center(child: RawChip(key: key1, label: const Text('test'))),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getSize(find.byKey(key1)).width, moreOrLessEquals(90.4, epsilon: 0.1));
|
||||
expect(tester.getSize(find.byKey(key1)).height, equals(48.0));
|
||||
expect(tester.getSize(find.byKey(key1)).width, moreOrLessEquals(90.4, epsilon: 0.1));
|
||||
expect(tester.getSize(find.byKey(key1)).height, equals(48.0));
|
||||
|
||||
final Key key2 = UniqueKey();
|
||||
await tester.pumpWidget(
|
||||
wrapForChip(
|
||||
child: Theme(
|
||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
|
||||
child: Center(child: RawChip(key: key2, label: const Text('test'))),
|
||||
),
|
||||
final Key key2 = UniqueKey();
|
||||
await tester.pumpWidget(
|
||||
wrapForChip(
|
||||
child: Theme(
|
||||
data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
|
||||
child: Center(child: RawChip(key: key2, label: const Text('test'))),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getSize(find.byKey(key2)).width, moreOrLessEquals(90.4, epsilon: 0.1));
|
||||
expect(tester.getSize(find.byKey(key2)).height, equals(38.0));
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
expect(tester.getSize(find.byKey(key2)).width, moreOrLessEquals(90.4, epsilon: 0.1));
|
||||
expect(tester.getSize(find.byKey(key2)).height, equals(38.0));
|
||||
});
|
||||
|
||||
testWidgets('Chip uses the right theme colors for the right components', (
|
||||
WidgetTester tester,
|
||||
@ -4599,7 +4597,7 @@ void main() {
|
||||
box = tester.getRect(find.byKey(key));
|
||||
expect(box.size.width, moreOrLessEquals(130.4, epsilon: 0.1));
|
||||
expect(box.size.height, equals(24.0 + 16.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Chip delete button tooltip is disabled if deleteButtonTooltipMessage is empty', (
|
||||
WidgetTester tester,
|
||||
@ -5897,86 +5895,84 @@ void main() {
|
||||
expect(materialBox, paints..rrect(color: backgroundColor));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'ChipAnimationStyle.avatarDrawerAnimation overrides chip avatar animation duration',
|
||||
(WidgetTester tester) async {
|
||||
const Color checkmarkColor = Color(0xffff0000);
|
||||
bool selected = false;
|
||||
testWidgets('ChipAnimationStyle.avatarDrawerAnimation overrides chip avatar animation duration', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const Color checkmarkColor = Color(0xffff0000);
|
||||
bool selected = false;
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
RawChip(
|
||||
chipAnimationStyle: ChipAnimationStyle(
|
||||
avatarDrawerAnimation: const AnimationStyle(
|
||||
duration: Duration(milliseconds: 800),
|
||||
reverseDuration: Duration(milliseconds: 400),
|
||||
),
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: Center(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
RawChip(
|
||||
chipAnimationStyle: ChipAnimationStyle(
|
||||
avatarDrawerAnimation: const AnimationStyle(
|
||||
duration: Duration(milliseconds: 800),
|
||||
reverseDuration: Duration(milliseconds: 400),
|
||||
),
|
||||
checkmarkColor: checkmarkColor,
|
||||
selected: selected,
|
||||
onSelected: (bool value) {},
|
||||
label: const Text('RawChip'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
selected = !selected;
|
||||
});
|
||||
},
|
||||
child: Text('${selected ? 'Unselect' : 'Select'} Chip'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
checkmarkColor: checkmarkColor,
|
||||
selected: selected,
|
||||
onSelected: (bool value) {},
|
||||
label: const Text('RawChip'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
selected = !selected;
|
||||
});
|
||||
},
|
||||
child: Text('${selected ? 'Unselect' : 'Select'} Chip'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
final RenderBox materialBox = tester.firstRenderObject<RenderBox>(
|
||||
find.descendant(of: find.byType(RawChip), matching: find.byType(CustomPaint)),
|
||||
);
|
||||
final RenderBox materialBox = tester.firstRenderObject<RenderBox>(
|
||||
find.descendant(of: find.byType(RawChip), matching: find.byType(CustomPaint)),
|
||||
);
|
||||
|
||||
// Test the checkmark is not visible yet.
|
||||
expect(materialBox, isNot(paints..path(color: checkmarkColor)));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(132.6, 0.1));
|
||||
// Test the checkmark is not visible yet.
|
||||
expect(materialBox, isNot(paints..path(color: checkmarkColor)));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(132.6, 0.1));
|
||||
|
||||
await tester.tap(find.widgetWithText(ElevatedButton, 'Select Chip'));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
await tester.tap(find.widgetWithText(ElevatedButton, 'Select Chip'));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
|
||||
expect(materialBox, paints..path(color: checkmarkColor));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(148.2, 0.1));
|
||||
expect(materialBox, paints..path(color: checkmarkColor));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(148.2, 0.1));
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
|
||||
// Test the checkmark is fully visible.
|
||||
expect(materialBox, paints..path(color: checkmarkColor));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(152.6, 0.1));
|
||||
// Test the checkmark is fully visible.
|
||||
expect(materialBox, paints..path(color: checkmarkColor));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(152.6, 0.1));
|
||||
|
||||
await tester.tap(find.widgetWithText(ElevatedButton, 'Unselect Chip'));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
await tester.tap(find.widgetWithText(ElevatedButton, 'Unselect Chip'));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
|
||||
expect(materialBox, isNot(paints..path(color: checkmarkColor)));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(148.2, 0.1));
|
||||
expect(materialBox, isNot(paints..path(color: checkmarkColor)));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(148.2, 0.1));
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
|
||||
// Test if checkmark is removed.
|
||||
expect(materialBox, isNot(paints..path(color: checkmarkColor)));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(132.6, 0.1));
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
// Test if checkmark is removed.
|
||||
expect(materialBox, isNot(paints..path(color: checkmarkColor)));
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(132.6, 0.1));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'ChipAnimationStyle.deleteDrawerAnimation overrides chip delete icon animation duration',
|
||||
@ -6048,7 +6044,6 @@ void main() {
|
||||
expect(find.byIcon(Icons.cancel), findsNothing);
|
||||
expect(tester.getSize(find.byType(RawChip)).width, closeTo(132.6, 0.1));
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
|
||||
testWidgets('Chip.chipAnimationStyle is passed to RawChip', (WidgetTester tester) async {
|
||||
|
@ -9,7 +9,6 @@ library;
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -898,10 +897,7 @@ void main() {
|
||||
final Offset subHeaderTextTopLeft = tester.getTopLeft(subHeaderText);
|
||||
final Offset dividerTopRight = tester.getTopRight(divider);
|
||||
expect(subHeaderTextTopLeft.dx, dividerTopRight.dx + 24.0);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(subHeaderTextTopLeft.dy, dialogTopLeft.dy + 16.0);
|
||||
}
|
||||
expect(subHeaderTextTopLeft.dy, dialogTopLeft.dy + 16.0);
|
||||
|
||||
// Test sub header icon position.
|
||||
final Finder subHeaderIcon = find.byIcon(Icons.arrow_drop_down);
|
||||
@ -915,10 +911,7 @@ void main() {
|
||||
final Offset calendarPageViewTopLeft = tester.getTopLeft(calendarPageView);
|
||||
final Offset subHeaderTextBottomLeft = tester.getBottomLeft(subHeaderText);
|
||||
expect(calendarPageViewTopLeft.dx, dividerTopRight.dx);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(calendarPageViewTopLeft.dy, subHeaderTextBottomLeft.dy + 16.0);
|
||||
}
|
||||
expect(calendarPageViewTopLeft.dy, subHeaderTextBottomLeft.dy + 16.0);
|
||||
|
||||
// Test month navigation icons position.
|
||||
final Finder previousMonthButton = find.widgetWithIcon(IconButton, Icons.chevron_left);
|
||||
@ -982,10 +975,7 @@ void main() {
|
||||
final Offset headerTextTextTopLeft = tester.getTopLeft(headerText);
|
||||
final Offset helpTextBottomLeft = tester.getBottomLeft(helpText);
|
||||
expect(headerTextTextTopLeft.dx, dialogTopLeft.dx + 24.0);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(headerTextTextTopLeft.dy, helpTextBottomLeft.dy + 28.0);
|
||||
}
|
||||
expect(headerTextTextTopLeft.dy, helpTextBottomLeft.dy + 28.0);
|
||||
|
||||
// Test switch button position.
|
||||
final Finder switchButtonM3 = find.widgetWithIcon(IconButton, Icons.edit_outlined);
|
||||
@ -1005,10 +995,7 @@ void main() {
|
||||
final Offset subHeaderTextTopLeft = tester.getTopLeft(subHeaderText);
|
||||
final Offset dividerBottomLeft = tester.getBottomLeft(divider);
|
||||
expect(subHeaderTextTopLeft.dx, dialogTopLeft.dx + 24.0);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(subHeaderTextTopLeft.dy, dividerBottomLeft.dy + 16.0);
|
||||
}
|
||||
expect(subHeaderTextTopLeft.dy, dividerBottomLeft.dy + 16.0);
|
||||
|
||||
// Test sub header icon position.
|
||||
final Finder subHeaderIcon = find.byIcon(Icons.arrow_drop_down);
|
||||
@ -1031,10 +1018,7 @@ void main() {
|
||||
final Offset calendarPageViewTopLeft = tester.getTopLeft(calendarPageView);
|
||||
final Offset subHeaderTextBottomLeft = tester.getBottomLeft(subHeaderText);
|
||||
expect(calendarPageViewTopLeft.dx, dialogTopLeft.dx);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(calendarPageViewTopLeft.dy, subHeaderTextBottomLeft.dy + 16.0);
|
||||
}
|
||||
expect(calendarPageViewTopLeft.dy, subHeaderTextBottomLeft.dy + 16.0);
|
||||
|
||||
// Test action buttons position.
|
||||
final Offset dialogBottomRight = tester.getBottomRight(find.byType(AnimatedContainer));
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -139,23 +138,14 @@ void main() {
|
||||
find.widgetWithIcon(IconButton, Icons.edit_outlined),
|
||||
);
|
||||
expect(saveButtonBottomLeft.dx, moreOrLessEquals(711.6, epsilon: 1e-5));
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(saveButtonBottomLeft.dy, helpTextTopLeft.dy);
|
||||
}
|
||||
expect(saveButtonBottomLeft.dy, helpTextTopLeft.dy);
|
||||
expect(entryButtonBottomLeft.dx, saveButtonBottomLeft.dx - 48.0);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(entryButtonBottomLeft.dy, helpTextTopLeft.dy);
|
||||
}
|
||||
expect(entryButtonBottomLeft.dy, helpTextTopLeft.dy);
|
||||
|
||||
// Test help text position.
|
||||
final Offset helpTextBottomLeft = tester.getBottomLeft(helpText);
|
||||
expect(helpTextBottomLeft.dx, 72.0);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(helpTextBottomLeft.dy, closeButtonBottomRight.dy + 20.0);
|
||||
}
|
||||
expect(helpTextBottomLeft.dy, closeButtonBottomRight.dy + 20.0);
|
||||
|
||||
// Test the header position.
|
||||
final Offset firstDateHeaderTopLeft = tester.getTopLeft(firstDateHeaderText);
|
||||
|
@ -428,10 +428,7 @@ void main() {
|
||||
find.descendant(of: find.byType(Dialog), matching: find.byType(Material)),
|
||||
);
|
||||
expect(bottomLeft.dx, 480.0);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(bottomLeft.dy, 124.0);
|
||||
}
|
||||
expect(bottomLeft.dy, 124.0);
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Dialog alignment takes priority over theme', (
|
||||
|
@ -7,7 +7,6 @@
|
||||
@Tags(<String>['reduced-test-set'])
|
||||
library;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
@ -847,7 +846,7 @@ void main() {
|
||||
// Test the delete button icon.
|
||||
expect(tester.getSize(find.byIcon(Icons.clear)), const Size(18.0, 18.0));
|
||||
expect(getIconData(tester).color, theme.colorScheme.onSurfaceVariant);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - FilterChip supports delete button', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData(useMaterial3: false);
|
||||
|
@ -7,7 +7,6 @@
|
||||
@Tags(<String>['reduced-test-set'])
|
||||
library;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -490,7 +489,7 @@ void main() {
|
||||
expect(semantics, hasSemantics(expectedSemantics, ignoreTransform: true));
|
||||
|
||||
semantics.dispose();
|
||||
}, skip: kIsWeb && !isCanvasKit); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Collapsed FlexibleSpaceBar has correct semantics', (
|
||||
WidgetTester tester,
|
||||
|
@ -119,7 +119,7 @@ void main() {
|
||||
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way
|
||||
|
||||
final RenderBox box = Material.of(tester.element(find.byType(InkWell))) as RenderBox;
|
||||
if (kIsWeb && isSkiaWeb) {
|
||||
if (kIsWeb) {
|
||||
expect(
|
||||
box,
|
||||
paints
|
||||
@ -153,7 +153,7 @@ void main() {
|
||||
);
|
||||
|
||||
await gesture.up();
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('The InkWell widget renders an ink ripple', (WidgetTester tester) async {
|
||||
const Color highlightColor = Color(0xAAFF0000);
|
||||
|
@ -118,11 +118,11 @@ void main() {
|
||||
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
|
||||
final MaterialInkController material = Material.of(tester.element(find.text('test')));
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
expect(material, paintsExactlyCountTimes(#drawRect, (kIsWeb && isSkiaWeb ? 1 : 2)));
|
||||
expect(material, paintsExactlyCountTimes(#drawRect, (kIsWeb ? 1 : 2)));
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/136441.
|
||||
testWidgets('PageView item can dispose when widget with NoSplash.splashFactory is tapped', (
|
||||
|
@ -4833,12 +4833,6 @@ void main() {
|
||||
const double helperStartPadding = 12.0;
|
||||
const double counterEndPadding = 12.0;
|
||||
|
||||
// Actual size varies a little on web platforms with HTML renderer.
|
||||
// TODO(bleroux): remove closeTo usage when https://github.com/flutter/flutter/issues/99933 is fixed.
|
||||
final Matcher closeToFullHeight = closeTo(fullHeight, 0.1);
|
||||
final Matcher closeToHelperHeight = closeTo(helperHeight, 0.1);
|
||||
final Matcher closeToErrorHeight = closeTo(errorHeight, 0.1);
|
||||
|
||||
group('for filled text field', () {
|
||||
group('when field is enabled', () {
|
||||
testWidgets('Helper and counter are correctly positioned', (WidgetTester tester) async {
|
||||
@ -4853,13 +4847,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -4897,13 +4891,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -4942,13 +4936,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -4987,13 +4981,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -5054,13 +5048,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getErrorRect(tester).top, containerHeight + helperGap);
|
||||
expect(getErrorRect(tester).height, closeToErrorHeight);
|
||||
expect(getErrorRect(tester).height, errorHeight);
|
||||
expect(getErrorRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToErrorHeight);
|
||||
expect(getCounterRect(tester).height, errorHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -5105,13 +5099,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -5149,13 +5143,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -5194,13 +5188,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -5239,13 +5233,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getHelperRect(tester).top, containerHeight + helperGap);
|
||||
expect(getHelperRect(tester).height, closeToHelperHeight);
|
||||
expect(getHelperRect(tester).height, helperHeight);
|
||||
expect(getHelperRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToHelperHeight);
|
||||
expect(getCounterRect(tester).height, helperHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
@ -5306,13 +5300,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(getDecoratorRect(tester).height, closeToFullHeight);
|
||||
expect(getDecoratorRect(tester).height, fullHeight);
|
||||
expect(getBorderBottom(tester), containerHeight);
|
||||
expect(getErrorRect(tester).top, containerHeight + helperGap);
|
||||
expect(getErrorRect(tester).height, closeToErrorHeight);
|
||||
expect(getErrorRect(tester).height, errorHeight);
|
||||
expect(getErrorRect(tester).left, helperStartPadding);
|
||||
expect(getCounterRect(tester).top, containerHeight + helperGap);
|
||||
expect(getCounterRect(tester).height, closeToErrorHeight);
|
||||
expect(getCounterRect(tester).height, errorHeight);
|
||||
expect(getCounterRect(tester).right, 800 - counterEndPadding);
|
||||
});
|
||||
|
||||
|
@ -160,10 +160,7 @@ void main() {
|
||||
await tester.pumpWidget(buildFrame(isTwoLine: true, textScaler: const TextScaler.linear(4.0)));
|
||||
testChildren();
|
||||
testHorizontalGeometry();
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
testVerticalGeometry(192.0);
|
||||
}
|
||||
testVerticalGeometry(192.0);
|
||||
|
||||
// Make sure that the height of a large subtitle is taken into account.
|
||||
await tester.pumpWidget(
|
||||
@ -175,20 +172,14 @@ void main() {
|
||||
);
|
||||
testChildren();
|
||||
testHorizontalGeometry();
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
testVerticalGeometry(108.0);
|
||||
}
|
||||
testVerticalGeometry(108.0);
|
||||
|
||||
await tester.pumpWidget(
|
||||
buildFrame(isThreeLine: true, textScaler: const TextScaler.linear(4.0)),
|
||||
);
|
||||
testChildren();
|
||||
testHorizontalGeometry();
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
testVerticalGeometry(192.0);
|
||||
}
|
||||
testVerticalGeometry(192.0);
|
||||
});
|
||||
|
||||
testWidgets('ListTile geometry (RTL)', (WidgetTester tester) async {
|
||||
@ -536,10 +527,6 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
if (kIsWeb && !isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
return;
|
||||
}
|
||||
const double height = 300;
|
||||
const double avatarTop = 130.0;
|
||||
const double placeholderTop = 138.0;
|
||||
|
@ -2655,187 +2655,176 @@ void main() {
|
||||
expect(closed, unorderedEquals(<TestMenu>[TestMenu.mainMenu1, TestMenu.subMenu11]));
|
||||
expect(opened, isEmpty);
|
||||
});
|
||||
}, skip: kIsWeb && !isCanvasKit); // https://github.com/flutter/flutter/issues/145527
|
||||
});
|
||||
|
||||
group('MenuItemButton', () {
|
||||
testWidgets(
|
||||
'Shortcut mnemonics are displayed',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const SingleActivator(
|
||||
LogicalKeyboardKey.keyA,
|
||||
control: true,
|
||||
),
|
||||
TestMenu.subSubMenu111: const SingleActivator(
|
||||
LogicalKeyboardKey.keyB,
|
||||
shift: true,
|
||||
),
|
||||
TestMenu.subSubMenu112: const SingleActivator(
|
||||
LogicalKeyboardKey.keyC,
|
||||
alt: true,
|
||||
),
|
||||
TestMenu.subSubMenu113: const SingleActivator(
|
||||
LogicalKeyboardKey.keyD,
|
||||
meta: true,
|
||||
),
|
||||
},
|
||||
),
|
||||
testWidgets('Shortcut mnemonics are displayed', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const SingleActivator(
|
||||
LogicalKeyboardKey.keyA,
|
||||
control: true,
|
||||
),
|
||||
TestMenu.subSubMenu111: const SingleActivator(
|
||||
LogicalKeyboardKey.keyB,
|
||||
shift: true,
|
||||
),
|
||||
TestMenu.subSubMenu112: const SingleActivator(LogicalKeyboardKey.keyC, alt: true),
|
||||
TestMenu.subSubMenu113: const SingleActivator(
|
||||
LogicalKeyboardKey.keyD,
|
||||
meta: true,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
// Open a menu initially.
|
||||
await tester.tap(find.text(TestMenu.mainMenu1.label));
|
||||
await tester.pump();
|
||||
// Open a menu initially.
|
||||
await tester.tap(find.text(TestMenu.mainMenu1.label));
|
||||
await tester.pump();
|
||||
|
||||
await tester.tap(find.text(TestMenu.subMenu11.label));
|
||||
await tester.pump();
|
||||
await tester.tap(find.text(TestMenu.subMenu11.label));
|
||||
await tester.pump();
|
||||
|
||||
Text mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
Text mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
Text mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
Text mnemonic3 = tester.widget(findMnemonic(TestMenu.subSubMenu113.label));
|
||||
Text mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
Text mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
Text mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
Text mnemonic3 = tester.widget(findMnemonic(TestMenu.subSubMenu113.label));
|
||||
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
case TargetPlatform.fuchsia:
|
||||
case TargetPlatform.linux:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Shift+B'));
|
||||
expect(mnemonic2.data, equals('Alt+C'));
|
||||
expect(mnemonic3.data, equals('Meta+D'));
|
||||
case TargetPlatform.windows:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Shift+B'));
|
||||
expect(mnemonic2.data, equals('Alt+C'));
|
||||
expect(mnemonic3.data, equals('Win+D'));
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
expect(mnemonic0.data, equals('⌃ A'));
|
||||
expect(mnemonic1.data, equals('⇧ B'));
|
||||
expect(mnemonic2.data, equals('⌥ C'));
|
||||
expect(mnemonic3.data, equals('⌘ D'));
|
||||
}
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
case TargetPlatform.fuchsia:
|
||||
case TargetPlatform.linux:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Shift+B'));
|
||||
expect(mnemonic2.data, equals('Alt+C'));
|
||||
expect(mnemonic3.data, equals('Meta+D'));
|
||||
case TargetPlatform.windows:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Shift+B'));
|
||||
expect(mnemonic2.data, equals('Alt+C'));
|
||||
expect(mnemonic3.data, equals('Win+D'));
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
expect(mnemonic0.data, equals('⌃ A'));
|
||||
expect(mnemonic1.data, equals('⇧ B'));
|
||||
expect(mnemonic2.data, equals('⌥ C'));
|
||||
expect(mnemonic3.data, equals('⌘ D'));
|
||||
}
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
includeExtraGroups: true,
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const SingleActivator(LogicalKeyboardKey.arrowRight),
|
||||
TestMenu.subSubMenu111: const SingleActivator(LogicalKeyboardKey.arrowLeft),
|
||||
TestMenu.subSubMenu112: const SingleActivator(LogicalKeyboardKey.arrowUp),
|
||||
TestMenu.subSubMenu113: const SingleActivator(LogicalKeyboardKey.arrowDown),
|
||||
},
|
||||
),
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
includeExtraGroups: true,
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const SingleActivator(LogicalKeyboardKey.arrowRight),
|
||||
TestMenu.subSubMenu111: const SingleActivator(LogicalKeyboardKey.arrowLeft),
|
||||
TestMenu.subSubMenu112: const SingleActivator(LogicalKeyboardKey.arrowUp),
|
||||
TestMenu.subSubMenu113: const SingleActivator(LogicalKeyboardKey.arrowDown),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
expect(mnemonic0.data, equals('→'));
|
||||
mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
expect(mnemonic1.data, equals('←'));
|
||||
mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
expect(mnemonic2.data, equals('↑'));
|
||||
mnemonic3 = tester.widget(findMnemonic(TestMenu.subSubMenu113.label));
|
||||
expect(mnemonic3.data, equals('↓'));
|
||||
mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
expect(mnemonic0.data, equals('→'));
|
||||
mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
expect(mnemonic1.data, equals('←'));
|
||||
mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
expect(mnemonic2.data, equals('↑'));
|
||||
mnemonic3 = tester.widget(findMnemonic(TestMenu.subSubMenu113.label));
|
||||
expect(mnemonic3.data, equals('↓'));
|
||||
|
||||
// Try some weirder ones.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const SingleActivator(LogicalKeyboardKey.escape),
|
||||
TestMenu.subSubMenu111: const SingleActivator(LogicalKeyboardKey.fn),
|
||||
TestMenu.subSubMenu112: const SingleActivator(LogicalKeyboardKey.enter),
|
||||
},
|
||||
),
|
||||
// Try some weirder ones.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const SingleActivator(LogicalKeyboardKey.escape),
|
||||
TestMenu.subSubMenu111: const SingleActivator(LogicalKeyboardKey.fn),
|
||||
TestMenu.subSubMenu112: const SingleActivator(LogicalKeyboardKey.enter),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
expect(mnemonic0.data, equals('Esc'));
|
||||
mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
expect(mnemonic1.data, equals('Fn'));
|
||||
mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
expect(mnemonic2.data, equals('↵'));
|
||||
},
|
||||
variant: TargetPlatformVariant.all(),
|
||||
skip: kIsWeb && !isCanvasKit, // https://github.com/flutter/flutter/issues/145527
|
||||
);
|
||||
mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
expect(mnemonic0.data, equals('Esc'));
|
||||
mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
expect(mnemonic1.data, equals('Fn'));
|
||||
mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
expect(mnemonic2.data, equals('↵'));
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/145040.
|
||||
testWidgets(
|
||||
'CharacterActivator shortcut mnemonics include modifiers',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const CharacterActivator('A', control: true),
|
||||
TestMenu.subSubMenu111: const CharacterActivator('B', alt: true),
|
||||
TestMenu.subSubMenu112: const CharacterActivator('C', meta: true),
|
||||
},
|
||||
),
|
||||
testWidgets('CharacterActivator shortcut mnemonics include modifiers', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Material(
|
||||
child: MenuBar(
|
||||
controller: controller,
|
||||
children: createTestMenus(
|
||||
shortcuts: <TestMenu, MenuSerializableShortcut>{
|
||||
TestMenu.subSubMenu110: const CharacterActivator('A', control: true),
|
||||
TestMenu.subSubMenu111: const CharacterActivator('B', alt: true),
|
||||
TestMenu.subSubMenu112: const CharacterActivator('C', meta: true),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
|
||||
// Open a menu initially.
|
||||
await tester.tap(find.text(TestMenu.mainMenu1.label));
|
||||
await tester.pump();
|
||||
// Open a menu initially.
|
||||
await tester.tap(find.text(TestMenu.mainMenu1.label));
|
||||
await tester.pump();
|
||||
|
||||
await tester.tap(find.text(TestMenu.subMenu11.label));
|
||||
await tester.pump();
|
||||
await tester.tap(find.text(TestMenu.subMenu11.label));
|
||||
await tester.pump();
|
||||
|
||||
final Text mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
final Text mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
final Text mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
final Text mnemonic0 = tester.widget(findMnemonic(TestMenu.subSubMenu110.label));
|
||||
final Text mnemonic1 = tester.widget(findMnemonic(TestMenu.subSubMenu111.label));
|
||||
final Text mnemonic2 = tester.widget(findMnemonic(TestMenu.subSubMenu112.label));
|
||||
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
case TargetPlatform.fuchsia:
|
||||
case TargetPlatform.linux:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Alt+B'));
|
||||
expect(mnemonic2.data, equals('Meta+C'));
|
||||
case TargetPlatform.windows:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Alt+B'));
|
||||
expect(mnemonic2.data, equals('Win+C'));
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
expect(mnemonic0.data, equals('⌃ A'));
|
||||
expect(mnemonic1.data, equals('⌥ B'));
|
||||
expect(mnemonic2.data, equals('⌘ C'));
|
||||
}
|
||||
},
|
||||
variant: TargetPlatformVariant.all(),
|
||||
skip: kIsWeb && !isCanvasKit, // https://github.com/flutter/flutter/issues/145527
|
||||
);
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
case TargetPlatform.fuchsia:
|
||||
case TargetPlatform.linux:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Alt+B'));
|
||||
expect(mnemonic2.data, equals('Meta+C'));
|
||||
case TargetPlatform.windows:
|
||||
expect(mnemonic0.data, equals('Ctrl+A'));
|
||||
expect(mnemonic1.data, equals('Alt+B'));
|
||||
expect(mnemonic2.data, equals('Win+C'));
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
expect(mnemonic0.data, equals('⌃ A'));
|
||||
expect(mnemonic1.data, equals('⌥ B'));
|
||||
expect(mnemonic2.data, equals('⌘ C'));
|
||||
}
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
|
||||
testWidgets('leadingIcon is used when set', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
@ -2925,7 +2914,7 @@ void main() {
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('trailingIcon'), findsOneWidget);
|
||||
}, skip: kIsWeb && !isCanvasKit); // https://github.com/flutter/flutter/issues/145527
|
||||
});
|
||||
|
||||
testWidgets('SubmenuButton uses supplied controller', (WidgetTester tester) async {
|
||||
final MenuController submenuController = MenuController();
|
||||
@ -3163,7 +3152,7 @@ void main() {
|
||||
// This should throw an error.
|
||||
final AssertionError exception = tester.takeException() as AssertionError;
|
||||
expect(exception, isAssertionError);
|
||||
}, skip: kIsWeb && !isCanvasKit); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('MenuItemButton.styleFrom overlayColor overrides default overlay color', (
|
||||
WidgetTester tester,
|
||||
@ -4005,7 +3994,7 @@ void main() {
|
||||
expect(find.text(allExpected), findsOneWidget);
|
||||
expect(find.text(charExpected), findsOneWidget);
|
||||
}, variant: TargetPlatformVariant.all());
|
||||
}, skip: kIsWeb && !isCanvasKit); // https://github.com/flutter/flutter/issues/145527
|
||||
});
|
||||
|
||||
group('CheckboxMenuButton', () {
|
||||
testWidgets('tapping toggles checkbox', (WidgetTester tester) async {
|
||||
@ -4425,7 +4414,7 @@ void main() {
|
||||
expect(material.textStyle?.fontStyle, menuTextStyle.fontStyle);
|
||||
expect(material.textStyle?.wordSpacing, menuTextStyle.wordSpacing);
|
||||
expect(material.textStyle?.decoration, menuTextStyle.decoration);
|
||||
}, skip: kIsWeb && !isCanvasKit); // https://github.com/flutter/flutter/issues/145527
|
||||
});
|
||||
|
||||
testWidgets('SubmenuButton.onFocusChange is respected', (WidgetTester tester) async {
|
||||
final FocusNode focusNode = FocusNode();
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
@ -78,14 +77,11 @@ void main() {
|
||||
expect(tester.getRect(findMenuPanels().first).size, equals(const Size(600.0, 60.0)));
|
||||
|
||||
// MenuTheme affects menus.
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
tester.getRect(findMenuPanels().at(1)),
|
||||
equals(const Rect.fromLTRB(104.0, 54.0, 204.0, 154.0)),
|
||||
);
|
||||
expect(tester.getRect(findMenuPanels().at(1)).size, equals(const Size(100.0, 100.0)));
|
||||
}
|
||||
expect(
|
||||
tester.getRect(findMenuPanels().at(1)),
|
||||
equals(const Rect.fromLTRB(104.0, 54.0, 204.0, 154.0)),
|
||||
);
|
||||
expect(tester.getRect(findMenuPanels().at(1)).size, equals(const Size(100.0, 100.0)));
|
||||
});
|
||||
|
||||
testWidgets('maximumSize affects geometry', (WidgetTester tester) async {
|
||||
|
@ -360,9 +360,7 @@ void main() {
|
||||
await tester.longPress(find.text(label));
|
||||
expect(find.text(label), findsNWidgets(2));
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
expect(tester.getSize(find.text(label).last), const Size(14.25, 20.0));
|
||||
}
|
||||
expect(tester.getSize(find.text(label).last), const Size(14.25, 20.0));
|
||||
// The duration is needed to ensure the tooltip disappears.
|
||||
await tester.pumpAndSettle(const Duration(seconds: 2));
|
||||
|
||||
@ -370,9 +368,7 @@ void main() {
|
||||
expect(find.text(label), findsOneWidget);
|
||||
await tester.longPress(find.text(label));
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
expect(tester.getSize(find.text(label).last), const Size(56.25, 80.0));
|
||||
}
|
||||
expect(tester.getSize(find.text(label).last), const Size(56.25, 80.0));
|
||||
});
|
||||
|
||||
testWidgets('Material3 - NavigationBar label can scale and has maxScaleFactor', (
|
||||
@ -413,31 +409,19 @@ void main() {
|
||||
|
||||
await tester.pumpWidget(buildApp(textScaler: TextScaler.noScaling));
|
||||
expect(find.text(label), findsOneWidget);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(12.5, 16.0)), true);
|
||||
}
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(12.5, 16.0)), true);
|
||||
|
||||
await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(1.1)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(13.7, 18.0)), true);
|
||||
}
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(13.7, 18.0)), true);
|
||||
|
||||
await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(1.3)));
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(16.1, 21.0)), true);
|
||||
}
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(16.1, 21.0)), true);
|
||||
|
||||
await tester.pumpWidget(buildApp(textScaler: const TextScaler.linear(4)));
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(16.1, 21.0)), true);
|
||||
}
|
||||
expect(_sizeAlmostEqual(tester.getSize(find.text(label)), const Size(16.1, 21.0)), true);
|
||||
});
|
||||
|
||||
testWidgets('Custom tooltips in NavigationBarDestination', (WidgetTester tester) async {
|
||||
@ -821,7 +805,7 @@ void main() {
|
||||
color: const Color(0x0a000000),
|
||||
),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material3 - Navigation indicator ripple golden test', (WidgetTester tester) async {
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/117420.
|
||||
|
@ -807,50 +807,41 @@ void main() {
|
||||
// The second destination is below the first with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox secondIconRenderBox = _iconRenderBox(tester, Icons.bookmark_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The third destination is below the second with some spacing.
|
||||
nextDestinationY += destinationHeight + destinationSpacing;
|
||||
final RenderBox thirdIconRenderBox = _iconRenderBox(tester, Icons.star_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The fourth destination is below the third with some spacing.
|
||||
nextDestinationY += destinationHeight + destinationSpacing;
|
||||
final RenderBox fourthIconRenderBox = _iconRenderBox(tester, Icons.hotel);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@ -912,50 +903,41 @@ void main() {
|
||||
// The second destination is below the first with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox secondIconRenderBox = _iconRenderBox(tester, Icons.bookmark_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The third destination is below the second with some spacing.
|
||||
nextDestinationY += destinationHeight + destinationSpacing;
|
||||
final RenderBox thirdIconRenderBox = _iconRenderBox(tester, Icons.star_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The fourth destination is below the third with some spacing.
|
||||
nextDestinationY += destinationHeight + destinationSpacing;
|
||||
final RenderBox fourthIconRenderBox = _iconRenderBox(tester, Icons.hotel);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Destination spacing is correct - [labelType]=selected, [textScaleFactor]=0.75', (
|
||||
@ -1016,50 +998,41 @@ void main() {
|
||||
// The second destination is below the first with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox secondIconRenderBox = _iconRenderBox(tester, Icons.bookmark_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The third destination is below the second with some spacing.
|
||||
nextDestinationY += destinationHeight + destinationSpacing;
|
||||
final RenderBox thirdIconRenderBox = _iconRenderBox(tester, Icons.star_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The fourth destination is below the third with some spacing.
|
||||
nextDestinationY += destinationHeight + destinationSpacing;
|
||||
final RenderBox fourthIconRenderBox = _iconRenderBox(tester, Icons.hotel);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Destination spacing is correct - [labelType]=all, [textScaleFactor]=1.0 (default)', (
|
||||
@ -1119,50 +1092,41 @@ void main() {
|
||||
// The second destination is below the first with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox secondIconRenderBox = _iconRenderBox(tester, Icons.bookmark_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The third destination is below the second with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox thirdIconRenderBox = _iconRenderBox(tester, Icons.star_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The fourth destination is below the third with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox fourthIconRenderBox = _iconRenderBox(tester, Icons.hotel);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Destination spacing is correct - [labelType]=all, [textScaleFactor]=3.0', (
|
||||
@ -1223,50 +1187,41 @@ void main() {
|
||||
// The second destination is below the first with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox secondIconRenderBox = _iconRenderBox(tester, Icons.bookmark_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The third destination is below the second with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox thirdIconRenderBox = _iconRenderBox(tester, Icons.star_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The fourth destination is below the third with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox fourthIconRenderBox = _iconRenderBox(tester, Icons.hotel);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Destination spacing is correct - [labelType]=all, [textScaleFactor]=0.75', (
|
||||
@ -1327,50 +1282,41 @@ void main() {
|
||||
// The second destination is below the first with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox secondIconRenderBox = _iconRenderBox(tester, Icons.bookmark_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
secondIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - secondIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - secondIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The third destination is below the second with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox thirdIconRenderBox = _iconRenderBox(tester, Icons.star_border);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
thirdIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - thirdIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - thirdIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
// The fourth destination is below the third with some spacing.
|
||||
nextDestinationY += destinationHeightWithLabel + destinationSpacing;
|
||||
final RenderBox fourthIconRenderBox = _iconRenderBox(tester, Icons.hotel);
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
expect(
|
||||
fourthIconRenderBox.localToGlobal(Offset.zero),
|
||||
equals(
|
||||
Offset(
|
||||
(destinationWidth - fourthIconRenderBox.size.width) / 2.0,
|
||||
nextDestinationY + (destinationHeight - fourthIconRenderBox.size.height) / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
@ -3164,7 +3110,7 @@ void main() {
|
||||
color: const Color(0xffe8def8),
|
||||
),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('NavigationRail indicator renders ripple - extended', (WidgetTester tester) async {
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/117126
|
||||
@ -3516,7 +3462,7 @@ void main() {
|
||||
color: const Color(0xffe8def8),
|
||||
),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('NavigationRail indicator renders properly with large icon', (
|
||||
WidgetTester tester,
|
||||
@ -3626,7 +3572,7 @@ void main() {
|
||||
color: const Color(0xffe8def8),
|
||||
),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('NavigationRail indicator renders properly when text direction is rtl', (
|
||||
WidgetTester tester,
|
||||
@ -3729,7 +3675,7 @@ void main() {
|
||||
color: const Color(0xffe8def8),
|
||||
),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('NavigationRail indicator scale transform', (WidgetTester tester) async {
|
||||
int selectedIndex = 0;
|
||||
@ -3967,7 +3913,7 @@ void main() {
|
||||
(RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures',
|
||||
);
|
||||
expect(inkFeatures, paints..circle(color: Colors.transparent));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Navigation rail can have expanded widgets inside', (WidgetTester tester) async {
|
||||
await _pumpNavigationRail(
|
||||
@ -4397,7 +4343,6 @@ void main() {
|
||||
),
|
||||
);
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
@ -4468,7 +4413,6 @@ void main() {
|
||||
),
|
||||
);
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
@ -4539,7 +4483,6 @@ void main() {
|
||||
),
|
||||
);
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
|
@ -1323,7 +1323,7 @@ void main() {
|
||||
|
||||
expect(tester.getSize(find.byType(OutlinedButton)), const Size(134.0, 48.0));
|
||||
expect(tester.getSize(find.byType(Text)), const Size(126.0, 42.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/122066
|
||||
});
|
||||
|
||||
testWidgets('OutlinedButton onPressed and onLongPress callbacks are distinctly recognized', (
|
||||
WidgetTester tester,
|
||||
|
@ -9,7 +9,6 @@ library;
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@ -929,7 +928,7 @@ void main() {
|
||||
|
||||
// The width of the SegmentedButton must be less than the width of the parent widget.
|
||||
expect(segmentedButtonWidth, lessThan(screenWidth));
|
||||
}, skip: kIsWeb && !isCanvasKit); // https://github.com/flutter/flutter/issues/145527
|
||||
});
|
||||
|
||||
testWidgets('SegmentedButton.styleFrom overlayColor overrides default overlay color', (
|
||||
WidgetTester tester,
|
||||
@ -1120,7 +1119,7 @@ void main() {
|
||||
p2: const Offset(166.8000030517578, tapTargetSize - 4.0),
|
||||
),
|
||||
);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('SegmentedButton vertical aligned children', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
|
@ -3046,11 +3046,7 @@ void main() {
|
||||
matchesGoldenFile('m3_snack_bar.scaffold.nested.png'),
|
||||
);
|
||||
final Offset snackBarTopRight = tester.getTopRight(find.byType(SnackBar));
|
||||
|
||||
if (!kIsWeb || isSkiaWeb) {
|
||||
// https://github.com/flutter/flutter/issues/99933
|
||||
expect(snackBarTopRight.dy, 465.0);
|
||||
}
|
||||
expect(snackBarTopRight.dy, 465.0);
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -1618,7 +1618,6 @@ void main() {
|
||||
labelSize = tester.getSize(find.text('Tab 1'));
|
||||
expect(labelSize, equals(const Size(140.5, 40.0)));
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/87543
|
||||
);
|
||||
|
||||
testWidgets('TabBarTheme indicatorAnimation can customize tab indicator animation', (
|
||||
|
@ -7539,7 +7539,6 @@ void main() {
|
||||
labelSize = tester.getSize(find.text('Tab 1'));
|
||||
expect(labelSize, equals(const Size(140.5, 40.0)));
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/87543
|
||||
);
|
||||
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/150000.
|
||||
|
@ -827,7 +827,7 @@ void main() {
|
||||
|
||||
expect(tester.getSize(find.byType(TextButton)), const Size(134.0, 48.0));
|
||||
expect(tester.getSize(find.byType(Text)), const Size(126.0, 42.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/61016
|
||||
});
|
||||
|
||||
testWidgets('TextButton size is configurable by ThemeData.materialTapTargetSize', (
|
||||
WidgetTester tester,
|
||||
|
@ -1175,7 +1175,7 @@ void main() {
|
||||
expect(firstToggleButtonDy, secondToggleButtonDy);
|
||||
expect(firstToggleButtonDy, closeTo(elevatedButtonDy - 1.7, 0.1));
|
||||
expect(firstToggleButtonDy, closeTo(textDy - 9.7, 0.1));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Directionality test', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
|
@ -202,7 +202,7 @@ void main() {
|
||||
final RenderBox tip = tester.renderObject(_findTooltipContainer(tooltipText));
|
||||
expect(tip.size.height, equals(24.0)); // 14.0 height + 5.0 padding * 2 (top, bottom)
|
||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)), equals(const Offset(10.0, 20.0)));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Material3 - Does tooltip end up in the right place - top left', (
|
||||
WidgetTester tester,
|
||||
@ -260,7 +260,7 @@ void main() {
|
||||
final RenderBox tip = tester.renderObject(_findTooltipContainer(tooltipText));
|
||||
expect(tip.size.height, equals(30.0)); // 20.0 height + 5.0 padding * 2 (top, bottom)
|
||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)), equals(const Offset(10.0, 20.0)));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Does tooltip end up in the right place - center prefer above fits', (
|
||||
WidgetTester tester,
|
||||
@ -514,51 +514,51 @@ void main() {
|
||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(324.0));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Material3 - Does tooltip end up in the right place - way off to the right',
|
||||
(WidgetTester tester) async {
|
||||
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
|
||||
late final OverlayEntry entry;
|
||||
addTearDown(
|
||||
() =>
|
||||
entry
|
||||
..remove()
|
||||
..dispose(),
|
||||
);
|
||||
testWidgets('Material3 - Does tooltip end up in the right place - way off to the right', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
|
||||
late final OverlayEntry entry;
|
||||
addTearDown(
|
||||
() =>
|
||||
entry
|
||||
..remove()
|
||||
..dispose(),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
entry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Positioned(
|
||||
left: 1600.0,
|
||||
top: 300.0,
|
||||
child: Tooltip(
|
||||
key: tooltipKey,
|
||||
message: tooltipText,
|
||||
height: 10.0,
|
||||
padding: EdgeInsets.zero,
|
||||
verticalOffset: 10.0,
|
||||
preferBelow: true,
|
||||
child: const SizedBox.shrink(),
|
||||
),
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
entry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Positioned(
|
||||
left: 1600.0,
|
||||
top: 300.0,
|
||||
child: Tooltip(
|
||||
key: tooltipKey,
|
||||
message: tooltipText,
|
||||
height: 10.0,
|
||||
padding: EdgeInsets.zero,
|
||||
verticalOffset: 10.0,
|
||||
preferBelow: true,
|
||||
child: const SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
tooltipKey.currentState?.ensureTooltipVisible();
|
||||
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
||||
),
|
||||
);
|
||||
tooltipKey.currentState?.ensureTooltipVisible();
|
||||
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
|
||||
|
||||
/********************* 800x600 screen
|
||||
/********************* 800x600 screen
|
||||
* *
|
||||
* *
|
||||
* * y=300.0; target --> o
|
||||
@ -568,14 +568,12 @@ void main() {
|
||||
* * }-10.0 margin
|
||||
*********************/
|
||||
|
||||
final RenderBox tip = tester.renderObject(_findTooltipContainer(tooltipText));
|
||||
expect(tip.size.height, equals(20.0));
|
||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(330.0));
|
||||
},
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
final RenderBox tip = tester.renderObject(_findTooltipContainer(tooltipText));
|
||||
expect(tip.size.height, equals(20.0));
|
||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(330.0));
|
||||
});
|
||||
|
||||
testWidgets('Material2 - Does tooltip end up in the right place - near the edge', (
|
||||
WidgetTester tester,
|
||||
@ -698,7 +696,7 @@ void main() {
|
||||
expect(tip.localToGlobal(tip.size.topLeft(Offset.zero)).dy, equals(310.0));
|
||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dx, equals(790.0));
|
||||
expect(tip.localToGlobal(tip.size.bottomRight(Offset.zero)).dy, equals(330.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Tooltip should be fully visible when MediaQuery.viewInsets > 0', (
|
||||
WidgetTester tester,
|
||||
@ -1207,7 +1205,6 @@ void main() {
|
||||
TargetPlatform.linux,
|
||||
TargetPlatform.windows,
|
||||
}),
|
||||
skip: kIsWeb && !isSkiaWeb, // https://github.com/flutter/flutter/issues/99933
|
||||
);
|
||||
|
||||
testWidgets('Material2 - Can tooltip decoration be customized', (WidgetTester tester) async {
|
||||
@ -2167,7 +2164,7 @@ void main() {
|
||||
expect(tester.getSize(find.text(tooltipText)).height, equals(80.0));
|
||||
tip = tester.renderObject(_findTooltipContainer(tooltipText));
|
||||
expect(tip.size.height, equals(88.0));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/99933
|
||||
});
|
||||
|
||||
testWidgets('Tooltip text displays with richMessage', (WidgetTester tester) async {
|
||||
final GlobalKey<TooltipState> tooltipKey = GlobalKey<TooltipState>();
|
||||
|
@ -139,7 +139,7 @@ void runTests() {
|
||||
});
|
||||
expect(recordedError, isNotNull);
|
||||
expect(imageInfo, isNull);
|
||||
}, skip: !isSkiaWeb);
|
||||
});
|
||||
|
||||
testWidgets('When strategy is .fallback, emits a WebImageInfo if the image is cross-origin', (
|
||||
WidgetTester tester,
|
||||
@ -191,7 +191,7 @@ void runTests() {
|
||||
|
||||
final WebImageInfo webImageInfo = imageInfo! as WebImageInfo;
|
||||
expect(webImageInfo.htmlImage.src, equals('https://www.example.com/images/frame5.png'));
|
||||
}, skip: !isSkiaWeb);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'When strategy is .fallback, emits an error if the image is cross-origin but fails to decode',
|
||||
@ -241,7 +241,6 @@ void runTests() {
|
||||
expect(recordedError, isNotNull);
|
||||
expect(imageInfo, isNull);
|
||||
},
|
||||
skip: !isSkiaWeb,
|
||||
);
|
||||
|
||||
testWidgets('When strategy is .prefer, emits an WebImageInfo if the image is same-origin', (
|
||||
@ -294,7 +293,7 @@ void runTests() {
|
||||
|
||||
final WebImageInfo webImageInfo = imageInfo! as WebImageInfo;
|
||||
expect(webImageInfo.htmlImage.src, equals('https://www.example.com/images/frame7.png'));
|
||||
}, skip: !isSkiaWeb);
|
||||
});
|
||||
|
||||
testWidgets('When strategy is .prefer, emits a normal image if headers is not null', (
|
||||
WidgetTester tester,
|
||||
@ -345,7 +344,7 @@ void runTests() {
|
||||
expect(recordedError, isNull);
|
||||
expect(imageInfo, isNotNull);
|
||||
expect(imageInfo, isNot(isA<WebImageInfo>()));
|
||||
}, skip: !isSkiaWeb);
|
||||
});
|
||||
|
||||
testWidgets('Image renders an image using a Platform View if the image info is WebImageInfo', (
|
||||
WidgetTester tester,
|
||||
@ -369,7 +368,7 @@ void runTests() {
|
||||
// After getting a WebImageInfo, the Image uses a Platform View to render.
|
||||
expect(find.byType(RawWebImage), findsOneWidget);
|
||||
expect(find.byType(PlatformViewLink), findsOneWidget);
|
||||
}, skip: !isSkiaWeb);
|
||||
});
|
||||
}
|
||||
|
||||
class _TestImageProvider extends ImageProvider<Object> {
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
@ -15,7 +14,7 @@ Future<void> main() async {
|
||||
debugCaptureShaderWarmUpImage = expectAsync1((ui.Image image) => true);
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
expect(shaderWarmUp.ranWarmUp, true);
|
||||
}, skip: kIsWeb && !isSkiaWeb); // [intended] Testing only for canvasKit
|
||||
});
|
||||
}
|
||||
|
||||
class FakeShaderWarmUp extends ShaderWarmUp {
|
||||
|
@ -217,7 +217,7 @@ void main() {
|
||||
verifyCharacterIsConsideredTrailingSpace('\u{205F}');
|
||||
|
||||
painter.dispose();
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('TextPainter caret test with WidgetSpan', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/98458.
|
||||
@ -244,7 +244,7 @@ void main() {
|
||||
);
|
||||
expect(caretOffset.dx, painter.width);
|
||||
painter.dispose();
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('TextPainter null text test', () {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
@ -346,7 +346,7 @@ void main() {
|
||||
caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 23), ui.Rect.zero);
|
||||
expect(caretOffset.dx, 126); // end of string
|
||||
painter.dispose();
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('TextPainter caret emoji tests: single, long emoji', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/50563
|
||||
@ -364,24 +364,20 @@ void main() {
|
||||
// their lengths in code units are powers of 2, namely 4 and 8).
|
||||
checkCaretOffsetsLtr('🇺🇳');
|
||||
checkCaretOffsetsLtr('👩❤️👨');
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test(
|
||||
'TextPainter caret emoji test: letters, then 1 emoji of 5 code units',
|
||||
() {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/50563
|
||||
checkCaretOffsetsLtr('a👩🚀');
|
||||
checkCaretOffsetsLtr('ab👩🚀');
|
||||
checkCaretOffsetsLtr('abc👩🚀');
|
||||
checkCaretOffsetsLtr('abcd👩🚀');
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
test('TextPainter caret emoji test: letters, then 1 emoji of 5 code units', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/50563
|
||||
checkCaretOffsetsLtr('a👩🚀');
|
||||
checkCaretOffsetsLtr('ab👩🚀');
|
||||
checkCaretOffsetsLtr('abc👩🚀');
|
||||
checkCaretOffsetsLtr('abcd👩🚀');
|
||||
});
|
||||
|
||||
test('TextPainter caret zalgo test', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/98516
|
||||
checkCaretOffsetsLtr('Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚');
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('TextPainter caret Devanagari test', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/118403
|
||||
@ -397,82 +393,74 @@ void main() {
|
||||
'व्रु',
|
||||
'ति',
|
||||
]);
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('TextPainter caret Devanagari test, full strength', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/118403
|
||||
checkCaretOffsetsLtr('प्राप्त वर्णन प्रव्रुति');
|
||||
}, skip: true); // https://github.com/flutter/flutter/issues/122478
|
||||
|
||||
test(
|
||||
'TextPainter caret emoji test LTR: letters next to emoji, as separate TextBoxes',
|
||||
() {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/122477
|
||||
// The trigger for this bug was to have SkParagraph report separate
|
||||
// TextBoxes for the emoji and for the characters next to it.
|
||||
// In normal usage on a real device, this can happen by simply typing
|
||||
// letters and then an emoji, presumably because they get different fonts.
|
||||
// In these tests, our single test font covers both letters and emoji,
|
||||
// so we provoke the same effect by adding styles.
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.ltr,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
TextSpan(text: ' words', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
test('TextPainter caret emoji test LTR: letters next to emoji, as separate TextBoxes', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/122477
|
||||
// The trigger for this bug was to have SkParagraph report separate
|
||||
// TextBoxes for the emoji and for the characters next to it.
|
||||
// In normal usage on a real device, this can happen by simply typing
|
||||
// letters and then an emoji, presumably because they get different fonts.
|
||||
// In these tests, our single test font covers both letters and emoji,
|
||||
// so we provoke the same effect by adding styles.
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.ltr,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
TextSpan(text: ' words', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
<double>[0, 28, 28, 28, 28, 28, 42, 56, 70, 84, 98, 112],
|
||||
);
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.ltr,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: 'words ', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
],
|
||||
),
|
||||
),
|
||||
<double>[0, 28, 28, 28, 28, 28, 42, 56, 70, 84, 98, 112],
|
||||
);
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.ltr,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: 'words ', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
],
|
||||
),
|
||||
<double>[0, 14, 28, 42, 56, 70, 84, 112, 112, 112, 112, 112],
|
||||
);
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
),
|
||||
<double>[0, 14, 28, 42, 56, 70, 84, 112, 112, 112, 112, 112],
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'TextPainter caret emoji test RTL: letters next to emoji, as separate TextBoxes',
|
||||
() {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/122477
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.rtl,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
TextSpan(text: ' מילים', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
test('TextPainter caret emoji test RTL: letters next to emoji, as separate TextBoxes', () {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/122477
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.rtl,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
TextSpan(text: ' מילים', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
<double>[112, 84, 84, 84, 84, 84, 70, 56, 42, 28, 14, 0],
|
||||
);
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.rtl,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: 'מילים ', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
],
|
||||
),
|
||||
),
|
||||
<double>[112, 84, 84, 84, 84, 84, 70, 56, 42, 28, 14, 0],
|
||||
);
|
||||
expect(
|
||||
caretOffsetsForTextSpan(
|
||||
TextDirection.rtl,
|
||||
const TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: 'מילים ', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextSpan(text: '👩🚀', style: TextStyle()),
|
||||
],
|
||||
),
|
||||
<double>[112, 98, 84, 70, 56, 42, 28, 0, 0, 0, 0, 0],
|
||||
);
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
),
|
||||
<double>[112, 98, 84, 70, 56, 42, 28, 0, 0, 0, 0, 0],
|
||||
);
|
||||
});
|
||||
|
||||
test('TextPainter caret center space test', () {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
@ -500,7 +488,7 @@ void main() {
|
||||
caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 2), ui.Rect.zero);
|
||||
expect(caretOffset.dx, 49);
|
||||
painter.dispose();
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('TextPainter caret height and line height', () {
|
||||
final TextPainter painter =
|
||||
@ -518,7 +506,7 @@ void main() {
|
||||
);
|
||||
expect(caretHeight, 50.0);
|
||||
painter.dispose();
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('upstream downstream makes no difference in the same line within the same bidi run', () {
|
||||
final TextPainter painter =
|
||||
@ -559,7 +547,7 @@ void main() {
|
||||
painter.getOffsetForCaret(TextPosition(offset: text.length), largeRect).dx,
|
||||
1000 - text.length * fontSize - largeRect.width,
|
||||
);
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('End of text caret when the text ends with +1 bidi level', () {
|
||||
const double fontSize = 14.0;
|
||||
@ -577,7 +565,7 @@ void main() {
|
||||
fontSize * 2 - largeRect.width,
|
||||
);
|
||||
expect(painter.getOffsetForCaret(const TextPosition(offset: 2), largeRect).dx, fontSize * 2);
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/56308
|
||||
});
|
||||
|
||||
test('handles newlines properly', () {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
@ -1243,7 +1231,7 @@ void main() {
|
||||
const TextBox.fromLTRBD(351, 30, 401, 60, TextDirection.ltr),
|
||||
);
|
||||
painter.dispose();
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/87540
|
||||
});
|
||||
|
||||
// Null values are valid. See https://github.com/flutter/flutter/pull/48346#issuecomment-584839221
|
||||
test('TextPainter set TextHeightBehavior null test', () {
|
||||
@ -1314,7 +1302,7 @@ void main() {
|
||||
expect(lines[2].lineNumber, 2);
|
||||
expect(lines[3].lineNumber, 3);
|
||||
painter.dispose();
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/122066
|
||||
});
|
||||
|
||||
group('TextPainter line-height', () {
|
||||
test('half-leading', () {
|
||||
@ -1453,7 +1441,7 @@ void main() {
|
||||
expect(glyphBox, newGlyphBox);
|
||||
painter.dispose();
|
||||
});
|
||||
}, skip: isBrowser && !isSkiaWeb); // https://github.com/flutter/flutter/issues/87543
|
||||
});
|
||||
|
||||
test('TextPainter handles invalid UTF-16', () {
|
||||
FlutterErrorDetails? error;
|
||||
@ -1488,7 +1476,7 @@ void main() {
|
||||
);
|
||||
expect(caretOffset.dx, painter.width);
|
||||
painter.dispose();
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/87545
|
||||
});
|
||||
|
||||
test('TextPainter line metrics update after layout', () {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
@ -1506,7 +1494,7 @@ void main() {
|
||||
lines = painter.computeLineMetrics();
|
||||
expect(lines.length, 1);
|
||||
painter.dispose();
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/62819
|
||||
});
|
||||
|
||||
test('TextPainter throws with stack trace when accessing text layout', () {
|
||||
final TextPainter painter =
|
||||
@ -1546,36 +1534,75 @@ void main() {
|
||||
painter.dispose();
|
||||
});
|
||||
|
||||
test(
|
||||
'TextPainter requires layout after providing different placeholder dimensions',
|
||||
() {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
test('TextPainter requires layout after providing different placeholder dimensions', () {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
|
||||
painter.text = const TextSpan(
|
||||
children: <InlineSpan>[
|
||||
TextSpan(text: 'before'),
|
||||
WidgetSpan(child: Text('widget1')),
|
||||
WidgetSpan(child: Text('widget2')),
|
||||
WidgetSpan(child: Text('widget3')),
|
||||
TextSpan(text: 'after'),
|
||||
],
|
||||
);
|
||||
painter.text = const TextSpan(
|
||||
children: <InlineSpan>[
|
||||
TextSpan(text: 'before'),
|
||||
WidgetSpan(child: Text('widget1')),
|
||||
WidgetSpan(child: Text('widget2')),
|
||||
WidgetSpan(child: Text('widget3')),
|
||||
TextSpan(text: 'after'),
|
||||
],
|
||||
);
|
||||
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
painter.layout();
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
painter.layout();
|
||||
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 20), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 20), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
|
||||
expect(
|
||||
() => painter.paint(MockCanvas(), Offset.zero),
|
||||
expect(
|
||||
() => painter.paint(MockCanvas(), Offset.zero),
|
||||
throwsA(
|
||||
isA<StateError>().having(
|
||||
(StateError error) => error.message,
|
||||
'message',
|
||||
contains('TextPainter.paint called when text geometry was not yet calculated'),
|
||||
),
|
||||
),
|
||||
);
|
||||
painter.dispose();
|
||||
});
|
||||
|
||||
test('TextPainter does not require layout after providing identical placeholder dimensions', () {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
|
||||
painter.text = const TextSpan(
|
||||
children: <InlineSpan>[
|
||||
TextSpan(text: 'before'),
|
||||
WidgetSpan(child: Text('widget1')),
|
||||
WidgetSpan(child: Text('widget2')),
|
||||
WidgetSpan(child: Text('widget3')),
|
||||
TextSpan(text: 'after'),
|
||||
],
|
||||
);
|
||||
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
painter.layout();
|
||||
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
|
||||
// In tests, paint() will throw an UnimplementedError due to missing drawParagraph method.
|
||||
expect(
|
||||
() => painter.paint(MockCanvas(), Offset.zero),
|
||||
isNot(
|
||||
throwsA(
|
||||
isA<StateError>().having(
|
||||
(StateError error) => error.message,
|
||||
@ -1583,57 +1610,10 @@ void main() {
|
||||
contains('TextPainter.paint called when text geometry was not yet calculated'),
|
||||
),
|
||||
),
|
||||
);
|
||||
painter.dispose();
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
|
||||
test(
|
||||
'TextPainter does not require layout after providing identical placeholder dimensions',
|
||||
() {
|
||||
final TextPainter painter = TextPainter()..textDirection = TextDirection.ltr;
|
||||
|
||||
painter.text = const TextSpan(
|
||||
children: <InlineSpan>[
|
||||
TextSpan(text: 'before'),
|
||||
WidgetSpan(child: Text('widget1')),
|
||||
WidgetSpan(child: Text('widget2')),
|
||||
WidgetSpan(child: Text('widget3')),
|
||||
TextSpan(text: 'after'),
|
||||
],
|
||||
);
|
||||
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
painter.layout();
|
||||
|
||||
painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: Size(30, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(40, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
PlaceholderDimensions(size: Size(50, 30), alignment: ui.PlaceholderAlignment.bottom),
|
||||
]);
|
||||
|
||||
// In tests, paint() will throw an UnimplementedError due to missing drawParagraph method.
|
||||
expect(
|
||||
() => painter.paint(MockCanvas(), Offset.zero),
|
||||
isNot(
|
||||
throwsA(
|
||||
isA<StateError>().having(
|
||||
(StateError error) => error.message,
|
||||
'message',
|
||||
contains('TextPainter.paint called when text geometry was not yet calculated'),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
painter.dispose();
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
),
|
||||
);
|
||||
painter.dispose();
|
||||
});
|
||||
|
||||
test('TextPainter - debugDisposed', () {
|
||||
final TextPainter painter = TextPainter();
|
||||
@ -1870,94 +1850,86 @@ void main() {
|
||||
case final List<ui.LineMetrics> metrics:
|
||||
expect(metrics, hasLength(1));
|
||||
}
|
||||
}, skip: kIsWeb && !isSkiaWeb); // [intended] Browsers seem to always round font/glyph metrics.
|
||||
});
|
||||
|
||||
group(
|
||||
'strut style',
|
||||
() {
|
||||
test('strut style applies when the span has no style', () {
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100);
|
||||
});
|
||||
group('strut style', () {
|
||||
test('strut style applies when the span has no style', () {
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100);
|
||||
});
|
||||
|
||||
test('strut style leading is a fontSize multiplier', () {
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10, leading: 2);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100 + 20);
|
||||
// Top leading + scaled ascent.
|
||||
expect(painter.computeDistanceToActualBaseline(TextBaseline.alphabetic), 10 + 10 * 7.5);
|
||||
});
|
||||
test('strut style leading is a fontSize multiplier', () {
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10, leading: 2);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100 + 20);
|
||||
// Top leading + scaled ascent.
|
||||
expect(painter.computeDistanceToActualBaseline(TextBaseline.alphabetic), 10 + 10 * 7.5);
|
||||
});
|
||||
|
||||
test('strut no half leading + force strut height', () {
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10, forceStrutHeight: true);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(text: 'A', style: TextStyle(fontSize: 20)),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100);
|
||||
const double baseline = 75;
|
||||
expect(
|
||||
painter.getBoxesForSelection(const TextSelection(baseOffset: 0, extentOffset: 1)),
|
||||
const <ui.TextBox>[
|
||||
TextBox.fromLTRBD(0, baseline - 15, 20, baseline + 5, TextDirection.ltr),
|
||||
],
|
||||
);
|
||||
});
|
||||
test('strut no half leading + force strut height', () {
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10, forceStrutHeight: true);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(text: 'A', style: TextStyle(fontSize: 20)),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100);
|
||||
const double baseline = 75;
|
||||
expect(
|
||||
painter.getBoxesForSelection(const TextSelection(baseOffset: 0, extentOffset: 1)),
|
||||
const <ui.TextBox>[
|
||||
TextBox.fromLTRBD(0, baseline - 15, 20, baseline + 5, TextDirection.ltr),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('strut half leading + force strut height', () {
|
||||
const StrutStyle strut = StrutStyle(
|
||||
height: 10,
|
||||
fontSize: 10,
|
||||
forceStrutHeight: true,
|
||||
leadingDistribution: TextLeadingDistribution.even,
|
||||
);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(text: 'A', style: TextStyle(fontSize: 20)),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100);
|
||||
const double baseline = 45 + 7.5;
|
||||
expect(
|
||||
painter.getBoxesForSelection(const TextSelection(baseOffset: 0, extentOffset: 1)),
|
||||
const <ui.TextBox>[
|
||||
TextBox.fromLTRBD(0, baseline - 15, 20, baseline + 5, TextDirection.ltr),
|
||||
],
|
||||
);
|
||||
});
|
||||
test('strut half leading + force strut height', () {
|
||||
const StrutStyle strut = StrutStyle(
|
||||
height: 10,
|
||||
fontSize: 10,
|
||||
forceStrutHeight: true,
|
||||
leadingDistribution: TextLeadingDistribution.even,
|
||||
);
|
||||
final TextPainter painter = TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const TextSpan(text: 'A', style: TextStyle(fontSize: 20)),
|
||||
strutStyle: strut,
|
||||
)..layout();
|
||||
expect(painter.height, 100);
|
||||
const double baseline = 45 + 7.5;
|
||||
expect(
|
||||
painter.getBoxesForSelection(const TextSelection(baseOffset: 0, extentOffset: 1)),
|
||||
const <ui.TextBox>[
|
||||
TextBox.fromLTRBD(0, baseline - 15, 20, baseline + 5, TextDirection.ltr),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('force strut height applies to widget spans', () {
|
||||
const Size placeholderSize = Size(1000, 1000);
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10, forceStrutHeight: true);
|
||||
final TextPainter painter =
|
||||
TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const WidgetSpan(child: SizedBox()),
|
||||
strutStyle: strut,
|
||||
)
|
||||
..setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(
|
||||
size: placeholderSize,
|
||||
alignment: PlaceholderAlignment.bottom,
|
||||
),
|
||||
])
|
||||
..layout();
|
||||
expect(painter.height, 100);
|
||||
});
|
||||
},
|
||||
// [intended] strut support for HTML renderer https://github.com/flutter/flutter/issues/32243.
|
||||
skip: kIsWeb && !isSkiaWeb,
|
||||
);
|
||||
test('force strut height applies to widget spans', () {
|
||||
const Size placeholderSize = Size(1000, 1000);
|
||||
const StrutStyle strut = StrutStyle(height: 10, fontSize: 10, forceStrutHeight: true);
|
||||
final TextPainter painter =
|
||||
TextPainter(
|
||||
textDirection: TextDirection.ltr,
|
||||
text: const WidgetSpan(child: SizedBox()),
|
||||
strutStyle: strut,
|
||||
)
|
||||
..setPlaceholderDimensions(const <PlaceholderDimensions>[
|
||||
PlaceholderDimensions(size: placeholderSize, alignment: PlaceholderAlignment.bottom),
|
||||
])
|
||||
..layout();
|
||||
expect(painter.height, 100);
|
||||
});
|
||||
});
|
||||
|
||||
test('getOffsetForCaret does not crash on decomposed characters', () {
|
||||
final TextPainter painter = TextPainter(
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -88,26 +87,21 @@ void main() {
|
||||
expect(editable.getMaxIntrinsicHeight(double.infinity), 10);
|
||||
});
|
||||
|
||||
test(
|
||||
'strutStyle affects intrinsics',
|
||||
() {
|
||||
final RenderEditable editable = RenderEditable(
|
||||
text: const TextSpan(style: TextStyle(fontSize: 10), text: 'Hello World'),
|
||||
textDirection: TextDirection.ltr,
|
||||
startHandleLayerLink: LayerLink(),
|
||||
endHandleLayerLink: LayerLink(),
|
||||
offset: ViewportOffset.zero(),
|
||||
textSelectionDelegate: delegate,
|
||||
);
|
||||
test('strutStyle affects intrinsics', () {
|
||||
final RenderEditable editable = RenderEditable(
|
||||
text: const TextSpan(style: TextStyle(fontSize: 10), text: 'Hello World'),
|
||||
textDirection: TextDirection.ltr,
|
||||
startHandleLayerLink: LayerLink(),
|
||||
endHandleLayerLink: LayerLink(),
|
||||
offset: ViewportOffset.zero(),
|
||||
textSelectionDelegate: delegate,
|
||||
);
|
||||
|
||||
expect(editable.getMaxIntrinsicHeight(double.infinity), 10);
|
||||
expect(editable.getMaxIntrinsicHeight(double.infinity), 10);
|
||||
|
||||
editable.strutStyle = const StrutStyle(fontSize: 100, forceStrutHeight: true);
|
||||
expect(editable.getMaxIntrinsicHeight(double.infinity), 100);
|
||||
},
|
||||
// [intended] strut support for HTML renderer https://github.com/flutter/flutter/issues/32243.
|
||||
skip: kIsWeb && !isSkiaWeb,
|
||||
);
|
||||
editable.strutStyle = const StrutStyle(fontSize: 100, forceStrutHeight: true);
|
||||
expect(editable.getMaxIntrinsicHeight(double.infinity), 100);
|
||||
});
|
||||
}
|
||||
|
||||
class _FakeEditableTextState with TextSelectionDelegate {
|
||||
|
@ -521,51 +521,41 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
test(
|
||||
'ContainerLayer.toImage can render interior layer',
|
||||
() {
|
||||
final OffsetLayer parent = OffsetLayer();
|
||||
final OffsetLayer child = OffsetLayer();
|
||||
final OffsetLayer grandChild = OffsetLayer();
|
||||
child.append(grandChild);
|
||||
parent.append(child);
|
||||
test('ContainerLayer.toImage can render interior layer', () {
|
||||
final OffsetLayer parent = OffsetLayer();
|
||||
final OffsetLayer child = OffsetLayer();
|
||||
final OffsetLayer grandChild = OffsetLayer();
|
||||
child.append(grandChild);
|
||||
parent.append(child);
|
||||
|
||||
// This renders the layers and generates engine layers.
|
||||
parent.buildScene(SceneBuilder());
|
||||
// This renders the layers and generates engine layers.
|
||||
parent.buildScene(SceneBuilder());
|
||||
|
||||
// Causes grandChild to pass its engine layer as `oldLayer`
|
||||
grandChild.toImage(const Rect.fromLTRB(0, 0, 10, 10));
|
||||
// Causes grandChild to pass its engine layer as `oldLayer`
|
||||
grandChild.toImage(const Rect.fromLTRB(0, 0, 10, 10));
|
||||
|
||||
// Ensure we can render the same scene again after rendering an interior
|
||||
// layer.
|
||||
parent.buildScene(SceneBuilder());
|
||||
},
|
||||
// TODO(yjbanov): `toImage` doesn't work in HTML: https://github.com/flutter/flutter/issues/49857
|
||||
skip: isBrowser && !isSkiaWeb,
|
||||
);
|
||||
// Ensure we can render the same scene again after rendering an interior
|
||||
// layer.
|
||||
parent.buildScene(SceneBuilder());
|
||||
});
|
||||
|
||||
test(
|
||||
'ContainerLayer.toImageSync can render interior layer',
|
||||
() {
|
||||
final OffsetLayer parent = OffsetLayer();
|
||||
final OffsetLayer child = OffsetLayer();
|
||||
final OffsetLayer grandChild = OffsetLayer();
|
||||
child.append(grandChild);
|
||||
parent.append(child);
|
||||
test('ContainerLayer.toImageSync can render interior layer', () {
|
||||
final OffsetLayer parent = OffsetLayer();
|
||||
final OffsetLayer child = OffsetLayer();
|
||||
final OffsetLayer grandChild = OffsetLayer();
|
||||
child.append(grandChild);
|
||||
parent.append(child);
|
||||
|
||||
// This renders the layers and generates engine layers.
|
||||
parent.buildScene(SceneBuilder());
|
||||
// This renders the layers and generates engine layers.
|
||||
parent.buildScene(SceneBuilder());
|
||||
|
||||
// Causes grandChild to pass its engine layer as `oldLayer`
|
||||
grandChild.toImageSync(const Rect.fromLTRB(0, 0, 10, 10));
|
||||
// Causes grandChild to pass its engine layer as `oldLayer`
|
||||
grandChild.toImageSync(const Rect.fromLTRB(0, 0, 10, 10));
|
||||
|
||||
// Ensure we can render the same scene again after rendering an interior
|
||||
// layer.
|
||||
parent.buildScene(SceneBuilder());
|
||||
},
|
||||
// TODO(yjbanov): `toImage` doesn't work in HTML: https://github.com/flutter/flutter/issues/49857
|
||||
skip: isBrowser && !isSkiaWeb,
|
||||
);
|
||||
// Ensure we can render the same scene again after rendering an interior
|
||||
// layer.
|
||||
parent.buildScene(SceneBuilder());
|
||||
});
|
||||
|
||||
test('PictureLayer does not let you call dispose unless refcount is 0', () {
|
||||
PictureLayer layer = PictureLayer(Rect.zero);
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
@ -85,20 +84,15 @@ void main() {
|
||||
expect(paragraph.getMaxIntrinsicHeight(double.infinity), 10);
|
||||
});
|
||||
|
||||
test(
|
||||
'strutStyle affects intrinsics',
|
||||
() {
|
||||
final RenderParagraph paragraph = RenderParagraph(
|
||||
const TextSpan(style: TextStyle(fontSize: 10), text: 'Hello World'),
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
test('strutStyle affects intrinsics', () {
|
||||
final RenderParagraph paragraph = RenderParagraph(
|
||||
const TextSpan(style: TextStyle(fontSize: 10), text: 'Hello World'),
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
|
||||
expect(paragraph.getMaxIntrinsicHeight(double.infinity), 10);
|
||||
expect(paragraph.getMaxIntrinsicHeight(double.infinity), 10);
|
||||
|
||||
paragraph.strutStyle = const StrutStyle(fontSize: 100, forceStrutHeight: true);
|
||||
expect(paragraph.getMaxIntrinsicHeight(double.infinity), 100);
|
||||
},
|
||||
// [intended] strut support for HTML renderer https://github.com/flutter/flutter/issues/32243.
|
||||
skip: kIsWeb && !isSkiaWeb,
|
||||
);
|
||||
paragraph.strutStyle = const StrutStyle(fontSize: 100, forceStrutHeight: true);
|
||||
expect(paragraph.getMaxIntrinsicHeight(double.infinity), 100);
|
||||
});
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle, Paragraph, TextBox;
|
||||
|
||||
import 'package:flutter/foundation.dart' show isSkiaWeb, kIsWeb;
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
@ -206,7 +205,7 @@ void main() {
|
||||
expect(boxes[2], const TextBox.fromLTRBD(0.0, 10.0, 130.0, 20.0, TextDirection.ltr));
|
||||
// 'fifth':
|
||||
expect(boxes[3], const TextBox.fromLTRBD(0.0, 20.0, 50.0, 30.0, TextDirection.ltr));
|
||||
}, skip: kIsWeb && !isSkiaWeb); // https://github.com/flutter/flutter/issues/61016
|
||||
});
|
||||
|
||||
test('getBoxesForSelection test with boxHeightStyle and boxWidthStyle set to max', () {
|
||||
final RenderParagraph paragraph = RenderParagraph(
|
||||
|
@ -1274,54 +1274,50 @@ void main() {
|
||||
expect(controller.text, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Caret center space test',
|
||||
(WidgetTester tester) async {
|
||||
EditableText.debugDeterministicCursor = true;
|
||||
addTearDown(() {
|
||||
EditableText.debugDeterministicCursor = false;
|
||||
});
|
||||
final String text = 'test${' ' * 1000}';
|
||||
final TextEditingController controller = TextEditingController.fromValue(
|
||||
TextEditingValue(
|
||||
text: text,
|
||||
selection: TextSelection.collapsed(offset: text.length, affinity: TextAffinity.upstream),
|
||||
),
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
testWidgets('Caret center space test', (WidgetTester tester) async {
|
||||
EditableText.debugDeterministicCursor = true;
|
||||
addTearDown(() {
|
||||
EditableText.debugDeterministicCursor = false;
|
||||
});
|
||||
final String text = 'test${' ' * 1000}';
|
||||
final TextEditingController controller = TextEditingController.fromValue(
|
||||
TextEditingValue(
|
||||
text: text,
|
||||
selection: TextSelection.collapsed(offset: text.length, affinity: TextAffinity.upstream),
|
||||
),
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
final Widget widget = EditableText(
|
||||
autofocus: true,
|
||||
backgroundCursorColor: Colors.grey,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
style: const TextStyle(fontSize: 17),
|
||||
textAlign: TextAlign.center,
|
||||
keyboardType: TextInputType.text,
|
||||
cursorColor: cursorColor,
|
||||
cursorWidth: 13.0,
|
||||
cursorHeight: 17.0,
|
||||
maxLines: null,
|
||||
);
|
||||
await tester.pumpWidget(MaterialApp(home: widget));
|
||||
final Widget widget = EditableText(
|
||||
autofocus: true,
|
||||
backgroundCursorColor: Colors.grey,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
style: const TextStyle(fontSize: 17),
|
||||
textAlign: TextAlign.center,
|
||||
keyboardType: TextInputType.text,
|
||||
cursorColor: cursorColor,
|
||||
cursorWidth: 13.0,
|
||||
cursorHeight: 17.0,
|
||||
maxLines: null,
|
||||
);
|
||||
await tester.pumpWidget(MaterialApp(home: widget));
|
||||
|
||||
final EditableTextState editableTextState = tester.firstState(find.byWidget(widget));
|
||||
final Rect editableTextRect = tester.getRect(find.byWidget(widget));
|
||||
final RenderEditable renderEditable = editableTextState.renderEditable;
|
||||
// The trailing whitespaces are not line break opportunities.
|
||||
expect(renderEditable.getLineAtOffset(TextPosition(offset: text.length)).start, 0);
|
||||
final EditableTextState editableTextState = tester.firstState(find.byWidget(widget));
|
||||
final Rect editableTextRect = tester.getRect(find.byWidget(widget));
|
||||
final RenderEditable renderEditable = editableTextState.renderEditable;
|
||||
// The trailing whitespaces are not line break opportunities.
|
||||
expect(renderEditable.getLineAtOffset(TextPosition(offset: text.length)).start, 0);
|
||||
|
||||
// The caretRect shouldn't be outside of the RenderEditable.
|
||||
final Rect caretRect = Rect.fromLTWH(
|
||||
editableTextRect.right - 13.0 - 1.0,
|
||||
editableTextRect.top,
|
||||
13.0,
|
||||
17.0,
|
||||
);
|
||||
expect(renderEditable, paints..rect(color: cursorColor, rect: caretRect));
|
||||
},
|
||||
skip: isBrowser && !isSkiaWeb, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
// The caretRect shouldn't be outside of the RenderEditable.
|
||||
final Rect caretRect = Rect.fromLTWH(
|
||||
editableTextRect.right - 13.0 - 1.0,
|
||||
editableTextRect.top,
|
||||
13.0,
|
||||
17.0,
|
||||
);
|
||||
expect(renderEditable, paints..rect(color: cursorColor, rect: caretRect));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'Caret with a cursorHeight smaller than font size is vertically centered on non-Apple platforms',
|
||||
@ -1364,7 +1360,6 @@ void main() {
|
||||
variant: TargetPlatformVariant.all(
|
||||
excluding: <TargetPlatform>{TargetPlatform.macOS, TargetPlatform.iOS},
|
||||
),
|
||||
skip: isBrowser && !isCanvasKit, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
@ -1408,7 +1403,6 @@ void main() {
|
||||
variant: TargetPlatformVariant.all(
|
||||
excluding: <TargetPlatform>{TargetPlatform.macOS, TargetPlatform.iOS},
|
||||
),
|
||||
skip: isBrowser && !isCanvasKit, // https://github.com/flutter/flutter/issues/56308
|
||||
);
|
||||
|
||||
testWidgets('getLocalRectForCaret reports the real caret Rect', (WidgetTester tester) async {
|
||||
|
@ -227,7 +227,6 @@ class SkiaGoldClient {
|
||||
'--png-file',
|
||||
goldenFile.path,
|
||||
'--passfail',
|
||||
..._getPixelMatchingArguments(),
|
||||
];
|
||||
|
||||
final io.ProcessResult result = await process.run(imgtestCommand);
|
||||
@ -365,7 +364,6 @@ class SkiaGoldClient {
|
||||
cleanTestName(testName),
|
||||
'--png-file',
|
||||
goldenFile.path,
|
||||
..._getPixelMatchingArguments(),
|
||||
];
|
||||
|
||||
final io.ProcessResult result = await process.run(imgtestCommand);
|
||||
@ -395,54 +393,6 @@ class SkiaGoldClient {
|
||||
return result.exitCode == 0 ? null : resultStdout;
|
||||
}
|
||||
|
||||
// Constructs arguments for `goldctl` for controlling how pixels are compared.
|
||||
//
|
||||
// For AOT and CanvasKit exact pixel matching is used. For the HTML renderer
|
||||
// on the web a fuzzy matching algorithm is used that allows very small deltas
|
||||
// because Chromium cannot exactly reproduce the same golden on all computers.
|
||||
// It seems to depend on the hardware/OS/driver combination. However, those
|
||||
// differences are very small (typically not noticeable to human eye).
|
||||
List<String> _getPixelMatchingArguments() {
|
||||
// Only use fuzzy pixel matching in the HTML renderer.
|
||||
if (!_isBrowserTest || _isBrowserSkiaTest) {
|
||||
return const <String>[];
|
||||
}
|
||||
|
||||
// The algorithm to be used when matching images. The available options are:
|
||||
// - "fuzzy": Allows for customizing the thresholds of pixel differences.
|
||||
// - "sobel": Same as "fuzzy" but performs edge detection before performing
|
||||
// a fuzzy match.
|
||||
const String algorithm = 'fuzzy';
|
||||
|
||||
// The number of pixels in this image that are allowed to differ from the
|
||||
// baseline.
|
||||
//
|
||||
// The chosen number - 20 - is arbitrary. Even for a small golden file, say
|
||||
// 50 x 50, it would be less than 1% of the total number of pixels. This
|
||||
// number should not grow too much. If it's growing, it is probably due to a
|
||||
// larger issue that needs to be addressed at the infra level.
|
||||
const int maxDifferentPixels = 20;
|
||||
|
||||
// The maximum acceptable difference per pixel.
|
||||
//
|
||||
// Uses the Manhattan distance using the RGBA color components as
|
||||
// coordinates. The chosen number - 4 - is arbitrary. It's small enough to
|
||||
// both not be noticeable and not trigger test flakes due to sub-pixel
|
||||
// golden deltas. This number should not grow too much. If it's growing, it
|
||||
// is probably due to a larger issue that needs to be addressed at the infra
|
||||
// level.
|
||||
const int pixelDeltaThreshold = 4;
|
||||
|
||||
return <String>[
|
||||
'--add-test-optional-key',
|
||||
'image_matching_algorithm:$algorithm',
|
||||
'--add-test-optional-key',
|
||||
'fuzzy_max_different_pixels:$maxDifferentPixels',
|
||||
'--add-test-optional-key',
|
||||
'fuzzy_pixel_delta_threshold:$pixelDeltaThreshold',
|
||||
];
|
||||
}
|
||||
|
||||
/// Returns the latest positive digest for the given test known to Flutter
|
||||
/// Gold at head.
|
||||
Future<String?> getExpectationForTest(String testName) async {
|
||||
|
@ -96,56 +96,6 @@ const List<int> _kTestPngBytes = <int>[
|
||||
|
||||
void main() {
|
||||
group('SkiaGoldClient', () {
|
||||
test('web HTML test', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem();
|
||||
final FakePlatform platform = FakePlatform(
|
||||
environment: <String, String>{
|
||||
'GOLDCTL': 'goldctl',
|
||||
'FLUTTER_ROOT': _kFlutterRoot,
|
||||
'FLUTTER_TEST_BROWSER': 'Chrome',
|
||||
'FLUTTER_WEB_RENDERER': 'html',
|
||||
},
|
||||
operatingSystem: 'macos',
|
||||
);
|
||||
final FakeProcessManager process = FakeProcessManager();
|
||||
final FakeHttpClient fakeHttpClient = FakeHttpClient();
|
||||
fs.directory(_kFlutterRoot).createSync(recursive: true);
|
||||
final Directory workDirectory = fs.directory('/workDirectory')..createSync(recursive: true);
|
||||
final SkiaGoldClient skiaClient = SkiaGoldClient(
|
||||
workDirectory,
|
||||
fs: fs,
|
||||
process: process,
|
||||
platform: platform,
|
||||
httpClient: fakeHttpClient,
|
||||
log: (String message) => fail('skia gold client printed unexpected output: "$message"'),
|
||||
);
|
||||
|
||||
final File goldenFile = fs.file('/workDirectory/temp/golden_file_test.png')
|
||||
..createSync(recursive: true);
|
||||
|
||||
const RunInvocation goldctlInvocation = RunInvocation(<String>[
|
||||
'goldctl',
|
||||
'imgtest',
|
||||
'add',
|
||||
'--work-dir',
|
||||
'/workDirectory/temp',
|
||||
'--test-name',
|
||||
'golden_file_test',
|
||||
'--png-file',
|
||||
'/workDirectory/temp/golden_file_test.png',
|
||||
'--passfail',
|
||||
'--add-test-optional-key',
|
||||
'image_matching_algorithm:fuzzy',
|
||||
'--add-test-optional-key',
|
||||
'fuzzy_max_different_pixels:20',
|
||||
'--add-test-optional-key',
|
||||
'fuzzy_pixel_delta_threshold:4',
|
||||
], null);
|
||||
process.processResults[goldctlInvocation] = ProcessResult(123, 0, '', '');
|
||||
|
||||
expect(await skiaClient.imgtestAdd('golden_file_test.png', goldenFile), isTrue);
|
||||
});
|
||||
|
||||
test('web CanvasKit test', () async {
|
||||
final MemoryFileSystem fs = MemoryFileSystem();
|
||||
final FakePlatform platform = FakePlatform(
|
||||
|
@ -7,7 +7,6 @@ import 'dart:js_interop';
|
||||
import 'dart:ui' as ui;
|
||||
import 'dart:ui_web' as ui_web;
|
||||
|
||||
import 'package:flutter/foundation.dart' show isSkiaWeb;
|
||||
import 'package:stream_channel/stream_channel.dart';
|
||||
import 'package:test_api/backend.dart';
|
||||
|
||||
@ -43,13 +42,7 @@ Future<void> runWebTest(WebTest test) async {
|
||||
await ui_web.bootstrapEngine(runApp: () => completer.complete());
|
||||
await completer.future;
|
||||
|
||||
// TODO(matanlurey): Remove webGoldenComparator when dart:html is deprecated.
|
||||
// See https://github.com/flutter/flutter/issues/145954.
|
||||
if (isSkiaWeb) {
|
||||
goldenFileComparator = HttpProxyGoldenComparator(test.goldensUri);
|
||||
} else {
|
||||
webGoldenComparator = DefaultWebGoldenComparator(test.goldensUri);
|
||||
}
|
||||
goldenFileComparator = HttpProxyGoldenComparator(test.goldensUri);
|
||||
|
||||
/// This hard-codes the device pixel ratio to 3.0 and a 2400 x 1800 window
|
||||
/// size for the purposes of testing.
|
||||
|
@ -478,9 +478,9 @@ void main() {
|
||||
// Tests whether using a deprecated webRenderer toggles a warningText.
|
||||
Future<void> testWebRendererDeprecationMessage(WebRendererMode webRenderer) async {
|
||||
testUsingContext(
|
||||
'Using --web-renderer=${webRenderer.name} triggers a warningText.',
|
||||
'Using the "${webRenderer.name}" renderer triggers a warningText.',
|
||||
() async {
|
||||
// Run the command so it parses --web-renderer, but ignore all errors.
|
||||
// Run the command so it parses the renderer, but ignore all errors.
|
||||
// We only care about the logger.
|
||||
try {
|
||||
final TestWebBuildCommand buildCommand = TestWebBuildCommand(fileSystem: fileSystem);
|
||||
|
@ -1130,9 +1130,9 @@ void main() {
|
||||
// Tests whether using a deprecated webRenderer toggles a warningText.
|
||||
Future<void> testWebRendererDeprecationMessage(WebRendererMode webRenderer) async {
|
||||
testUsingContext(
|
||||
'Using --web-renderer=${webRenderer.name} triggers a warningText.',
|
||||
'Using the "${webRenderer.name}" renderer triggers a warningText.',
|
||||
() async {
|
||||
// Run the command so it parses --web-renderer, but ignore all errors.
|
||||
// Run the command so it parses the renderer, but ignore all errors.
|
||||
// We only care about the logger.
|
||||
try {
|
||||
await createTestCommandRunner(
|
||||
|
@ -1528,9 +1528,9 @@ dev_dependencies:
|
||||
// Tests whether using a deprecated webRenderer toggles a warningText.
|
||||
Future<void> testWebRendererDeprecationMessage(WebRendererMode webRenderer) async {
|
||||
testUsingContext(
|
||||
'Using --web-renderer=${webRenderer.name} triggers a warningText.',
|
||||
'Using the "${webRenderer.name}" renderer triggers a warningText.',
|
||||
() async {
|
||||
// Run the command so it parses --web-renderer, but ignore all errors.
|
||||
// Run the command so it parses the renderer, but ignore all errors.
|
||||
// We only care about the logger.
|
||||
try {
|
||||
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
|
||||
|
@ -8,7 +8,6 @@ library;
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/web/compile.dart';
|
||||
|
||||
import '../integration.shard/test_data/hot_reload_project.dart';
|
||||
import '../integration.shard/test_driver.dart';
|
||||
@ -74,30 +73,6 @@ Future<void> _testProject(HotReloadProject project, {String name = 'Default'}) a
|
||||
await flutter.hotRestart();
|
||||
});
|
||||
|
||||
testWithoutContext(
|
||||
'$testName: newly added code executes during hot restart - html (legacy)',
|
||||
() async {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
final StreamSubscription<String> subscription = flutter.stdout.listen((String line) {
|
||||
printOnFailure(line);
|
||||
if (line.contains('(((((RELOAD WORKED)))))')) {
|
||||
completer.complete();
|
||||
}
|
||||
});
|
||||
await flutter.run(
|
||||
chrome: true,
|
||||
additionalCommandArgs: <String>['--verbose', ...WebRendererMode.html.toCliDartDefines],
|
||||
);
|
||||
project.uncommentHotReloadPrint();
|
||||
try {
|
||||
await flutter.hotRestart();
|
||||
await completer.future.timeout(const Duration(seconds: 15));
|
||||
} finally {
|
||||
await subscription.cancel();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
testWithoutContext(
|
||||
'$testName: newly added code executes during hot restart - canvaskit',
|
||||
() async {
|
||||
|
Loading…
x
Reference in New Issue
Block a user