mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
* Update project.pbxproj files to say Flutter rather than Chromium Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright. * Update the copyright notice checker to require a standard notice on all files * Update copyrights on Dart files. (This was a mechanical commit.) * Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine. Some were already marked "The Flutter Authors", not clear why. Their dates have been normalized. Some were missing the blank line after the license. Some were randomly different in trivial ways for no apparent reason (e.g. missing the trailing period). * Clean up the copyrights in non-Dart files. (Manual edits.) Also, make sure templates don't have copyrights. * Fix some more ORGANIZATIONNAMEs
513 lines
16 KiB
Dart
513 lines
16 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../rendering/mock_canvas.dart';
|
|
|
|
void main() {
|
|
|
|
// The "can be constructed" tests that follow are primarily to ensure that any
|
|
// animations started by the progress indicators are stopped at dispose() time.
|
|
|
|
testWidgets('LinearProgressIndicator(value: 0.0) can be constructed and has empty semantics by default', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: LinearProgressIndicator(value: 0.0),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byType(LinearProgressIndicator)), matchesSemantics());
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator(value: null) can be constructed and has empty semantics by default', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: LinearProgressIndicator(value: null),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byType(LinearProgressIndicator)), matchesSemantics());
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator paint (LTR)', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: LinearProgressIndicator(value: 0.25),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 6.0))
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 50.0, 6.0)),
|
|
);
|
|
|
|
expect(tester.binding.transientCallbackCount, 0);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator paint (RTL)', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: LinearProgressIndicator(value: 0.25),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 6.0))
|
|
..rect(rect: const Rect.fromLTRB(150.0, 0.0, 200.0, 6.0)),
|
|
);
|
|
|
|
expect(tester.binding.transientCallbackCount, 0);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator indeterminate (LTR)', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: LinearProgressIndicator(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pump(const Duration(milliseconds: 300));
|
|
final double animationValue = const Interval(0.0, 750.0 / 1800.0, curve: Cubic(0.2, 0.0, 0.8, 1.0))
|
|
.transform(300.0 / 1800.0);
|
|
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 6.0))
|
|
..rect(rect: Rect.fromLTRB(0.0, 0.0, animationValue * 200.0, 6.0)),
|
|
);
|
|
|
|
expect(tester.binding.transientCallbackCount, 1);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator paint (RTL)', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: LinearProgressIndicator(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pump(const Duration(milliseconds: 300));
|
|
final double animationValue = const Interval(0.0, 750.0 / 1800.0, curve: Cubic(0.2, 0.0, 0.8, 1.0))
|
|
.transform(300.0 / 1800.0);
|
|
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 6.0))
|
|
..rect(rect: Rect.fromLTRB(200.0 - animationValue * 200.0, 0.0, 200.0, 6.0)),
|
|
);
|
|
|
|
expect(tester.binding.transientCallbackCount, 1);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator with colors', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: LinearProgressIndicator(
|
|
value: 0.25,
|
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
|
backgroundColor: Colors.black,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 200.0, 6.0))
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 50.0, 6.0), color: Colors.white),
|
|
);
|
|
});
|
|
|
|
testWidgets('CircularProgressIndicator(value: 0.0) can be constructed and has value semantics by default', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: CircularProgressIndicator(value: 0.0),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byType(CircularProgressIndicator)), matchesSemantics(
|
|
value: '0%',
|
|
textDirection: TextDirection.ltr,
|
|
));
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('CircularProgressIndicator(value: null) can be constructed and has empty semantics by default', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
await tester.pumpWidget(
|
|
const Center(
|
|
child: CircularProgressIndicator(value: null),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byType(CircularProgressIndicator)), matchesSemantics());
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator causes a repaint when it changes', (WidgetTester tester) async {
|
|
await tester.pumpWidget(Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: ListView(children: const <Widget>[LinearProgressIndicator(value: 0.0)]),
|
|
));
|
|
final List<Layer> layers1 = tester.layers;
|
|
await tester.pumpWidget(Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: ListView(children: const <Widget>[LinearProgressIndicator(value: 0.5)])),
|
|
);
|
|
final List<Layer> layers2 = tester.layers;
|
|
expect(layers1, isNot(equals(layers2)));
|
|
});
|
|
|
|
testWidgets('CircularProgressIndicator stoke width', (WidgetTester tester) async {
|
|
await tester.pumpWidget(const CircularProgressIndicator());
|
|
|
|
expect(find.byType(CircularProgressIndicator), paints..arc(strokeWidth: 4.0));
|
|
|
|
await tester.pumpWidget(const CircularProgressIndicator(strokeWidth: 16.0));
|
|
|
|
expect(find.byType(CircularProgressIndicator), paints..arc(strokeWidth: 16.0));
|
|
});
|
|
|
|
testWidgets('CircularProgressIndicator paint background color', (WidgetTester tester) async {
|
|
const Color green = Color(0xFF00FF00);
|
|
const Color blue = Color(0xFF0000FF);
|
|
|
|
await tester.pumpWidget(const CircularProgressIndicator(
|
|
valueColor: AlwaysStoppedAnimation<Color>(blue),
|
|
));
|
|
|
|
expect(find.byType(CircularProgressIndicator), paintsExactlyCountTimes(#drawArc, 1));
|
|
expect(find.byType(CircularProgressIndicator), paints..arc(color: blue));
|
|
|
|
await tester.pumpWidget(const CircularProgressIndicator(
|
|
backgroundColor: green,
|
|
valueColor: AlwaysStoppedAnimation<Color>(blue),
|
|
));
|
|
|
|
expect(find.byType(CircularProgressIndicator), paintsExactlyCountTimes(#drawArc, 2));
|
|
expect(find.byType(CircularProgressIndicator), paints..arc(color: green)..arc(color: blue));
|
|
});
|
|
|
|
testWidgets('Indeterminate RefreshProgressIndicator keeps spinning until end of time (approximate)', (WidgetTester tester) async {
|
|
// Regression test for https://github.com/flutter/flutter/issues/13782
|
|
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 200.0,
|
|
child: RefreshProgressIndicator(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(tester.hasRunningAnimations, isTrue);
|
|
|
|
await tester.pump(const Duration(seconds: 5));
|
|
expect(tester.hasRunningAnimations, isTrue);
|
|
|
|
await tester.pump(const Duration(milliseconds: 1));
|
|
expect(tester.hasRunningAnimations, isTrue);
|
|
|
|
await tester.pump(const Duration(days: 9999));
|
|
expect(tester.hasRunningAnimations, isTrue);
|
|
});
|
|
|
|
testWidgets('Determinate CircularProgressIndicator stops the animator', (WidgetTester tester) async {
|
|
double progressValue;
|
|
StateSetter setState;
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: StatefulBuilder(
|
|
builder: (BuildContext context, StateSetter setter) {
|
|
setState = setter;
|
|
return CircularProgressIndicator(value: progressValue);
|
|
}
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(tester.hasRunningAnimations, isTrue);
|
|
|
|
setState(() { progressValue = 1.0; });
|
|
await tester.pump(const Duration(milliseconds: 1));
|
|
expect(tester.hasRunningAnimations, isFalse);
|
|
|
|
setState(() { progressValue = null; });
|
|
await tester.pump(const Duration(milliseconds: 1));
|
|
expect(tester.hasRunningAnimations, isTrue);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator with height 12.0', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 100.0,
|
|
height: 12.0,
|
|
child: LinearProgressIndicator(value: 0.25),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 100.0, 12.0))
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 25.0, 12.0)),
|
|
);
|
|
expect(tester.binding.transientCallbackCount, 0);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator with a height less than the minumum', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 100.0,
|
|
height: 3.0,
|
|
child: LinearProgressIndicator(value: 0.25),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 100.0, 3.0))
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 25.0, 3.0)),
|
|
);
|
|
expect(tester.binding.transientCallbackCount, 0);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator with default height', (WidgetTester tester) async {
|
|
await tester.pumpWidget(
|
|
const Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: Center(
|
|
child: SizedBox(
|
|
width: 100.0,
|
|
height: 4.0,
|
|
child: LinearProgressIndicator(value: 0.25),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
expect(
|
|
find.byType(LinearProgressIndicator),
|
|
paints
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 100.0, 4.0))
|
|
..rect(rect: const Rect.fromLTRB(0.0, 0.0, 25.0, 4.0)),
|
|
);
|
|
expect(tester.binding.transientCallbackCount, 0);
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator can be made accessible', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final GlobalKey key = GlobalKey();
|
|
const String label = 'Label';
|
|
const String value = '25%';
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: LinearProgressIndicator(
|
|
key: key,
|
|
value: 0.25,
|
|
semanticsLabel: label,
|
|
semanticsValue: value,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
|
|
textDirection: TextDirection.ltr,
|
|
label: label,
|
|
value: value,
|
|
));
|
|
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator that is determinate gets default a11y value', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final GlobalKey key = GlobalKey();
|
|
const String label = 'Label';
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: LinearProgressIndicator(
|
|
key: key,
|
|
value: 0.25,
|
|
semanticsLabel: label,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
|
|
textDirection: TextDirection.ltr,
|
|
label: label,
|
|
value: '25%',
|
|
));
|
|
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator that is determinate does not default a11y value when label is null', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final GlobalKey key = GlobalKey();
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: LinearProgressIndicator(
|
|
key: key,
|
|
value: 0.25,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byKey(key)), matchesSemantics());
|
|
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('LinearProgressIndicator that is indeterminate does not default a11y value', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final GlobalKey key = GlobalKey();
|
|
const String label = 'Progress';
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: LinearProgressIndicator(
|
|
key: key,
|
|
value: 0.25,
|
|
semanticsLabel: label,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
|
|
textDirection: TextDirection.ltr,
|
|
label: label,
|
|
));
|
|
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('CircularProgressIndicator can be made accessible', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final GlobalKey key = GlobalKey();
|
|
const String label = 'Label';
|
|
const String value = '25%';
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: CircularProgressIndicator(
|
|
key: key,
|
|
value: 0.25,
|
|
semanticsLabel: label,
|
|
semanticsValue: value,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
|
|
textDirection: TextDirection.ltr,
|
|
label: label,
|
|
value: value,
|
|
));
|
|
|
|
handle.dispose();
|
|
});
|
|
|
|
testWidgets('RefreshProgressIndicator can be made accessible', (WidgetTester tester) async {
|
|
final SemanticsHandle handle = tester.ensureSemantics();
|
|
final GlobalKey key = GlobalKey();
|
|
const String label = 'Label';
|
|
const String value = '25%';
|
|
await tester.pumpWidget(
|
|
Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: RefreshProgressIndicator(
|
|
key: key,
|
|
semanticsLabel: label,
|
|
semanticsValue: value,
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(tester.getSemantics(find.byKey(key)), matchesSemantics(
|
|
textDirection: TextDirection.ltr,
|
|
label: label,
|
|
value: value,
|
|
));
|
|
|
|
|
|
handle.dispose();
|
|
});
|
|
}
|