493 lines
20 KiB
Dart
493 lines
20 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/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'semantics_tester.dart';
|
|
|
|
class TestState extends StatefulWidget {
|
|
const TestState({super.key, required this.child, required this.log});
|
|
final Widget child;
|
|
final List<String> log;
|
|
@override
|
|
State<TestState> createState() => _TestStateState();
|
|
}
|
|
|
|
class _TestStateState extends State<TestState> {
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
widget.log.add('created new state');
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return widget.child;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
testWidgets('SliverVisibility', (WidgetTester tester) async {
|
|
final semantics = SemanticsTester(tester);
|
|
final log = <String>[];
|
|
const anchor = Key('drag');
|
|
|
|
Widget boilerPlate(Widget sliver) {
|
|
return Localizations(
|
|
locale: const Locale('en', 'us'),
|
|
delegates: const <LocalizationsDelegate<dynamic>>[
|
|
DefaultWidgetsLocalizations.delegate,
|
|
DefaultMaterialLocalizations.delegate,
|
|
],
|
|
child: Directionality(
|
|
textDirection: TextDirection.ltr,
|
|
child: MediaQuery(
|
|
data: const MediaQueryData(),
|
|
child: CustomScrollView(slivers: <Widget>[sliver]),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
final Widget testChild = SliverToBoxAdapter(
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
log.add('tap');
|
|
},
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
final bool animating = TickerMode.of(context);
|
|
return TestState(
|
|
key: anchor,
|
|
log: log,
|
|
child: Text('a $animating', textDirection: TextDirection.rtl),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
|
|
// We now run a sequence of pumpWidget calls one after the other. In
|
|
// addition to verifying that the right behavior is seen in each case, this
|
|
// also verifies that the widget can dynamically change from state to state.
|
|
|
|
// Default
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild)));
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paints..paragraph());
|
|
RenderViewport renderViewport = tester.renderObject(find.byType(Viewport));
|
|
RenderSliver renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>['created new state']);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['created new state', 'tap']);
|
|
log.clear();
|
|
|
|
// visible: false
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild, visible: false)));
|
|
expect(find.byType(Text), findsNothing);
|
|
expect(find.byType(Text, skipOffstage: false), findsNothing);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 0.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// visible: false, with replacementSliver
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
replacementSliver: const SliverToBoxAdapter(child: Placeholder()),
|
|
visible: false,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsNothing);
|
|
expect(find.byType(Placeholder), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paints..path());
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 400.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// visible: true, with replacementSliver
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
replacementSliver: const SliverToBoxAdapter(child: Placeholder()),
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(Placeholder), findsNothing);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paints..paragraph());
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>['created new state']);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['created new state', 'tap']);
|
|
log.clear();
|
|
|
|
// visible: true, maintain all
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
maintainState: true,
|
|
maintainAnimation: true,
|
|
maintainSize: true,
|
|
maintainInteractivity: true,
|
|
maintainSemantics: true,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paints..paragraph());
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>['created new state']);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['created new state', 'tap']);
|
|
log.clear();
|
|
|
|
// visible: false, maintain all
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
visible: false,
|
|
maintainState: true,
|
|
maintainAnimation: true,
|
|
maintainSize: true,
|
|
maintainInteractivity: true,
|
|
maintainSemantics: true,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>[]);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['tap']);
|
|
log.clear();
|
|
|
|
// visible: false, maintain all, replacementSliver
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
replacementSliver: const SliverToBoxAdapter(child: Placeholder()),
|
|
visible: false,
|
|
maintainState: true,
|
|
maintainAnimation: true,
|
|
maintainSize: true,
|
|
maintainInteractivity: true,
|
|
maintainSemantics: true,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(Placeholder), findsNothing);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>[]);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['tap']);
|
|
log.clear();
|
|
|
|
// visible: false, maintain all but semantics
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
visible: false,
|
|
maintainState: true,
|
|
maintainAnimation: true,
|
|
maintainSize: true,
|
|
maintainInteractivity: true,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['tap']);
|
|
log.clear();
|
|
|
|
// visible: false, maintain all but interactivity
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
visible: false,
|
|
maintainState: true,
|
|
maintainAnimation: true,
|
|
maintainSize: true,
|
|
maintainSemantics: true,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>[]);
|
|
await tester.tap(find.byKey(anchor), warnIfMissed: false);
|
|
expect(log, <String>[]);
|
|
log.clear();
|
|
|
|
// visible: false, maintain state, animation, size.
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
visible: false,
|
|
maintainState: true,
|
|
maintainAnimation: true,
|
|
maintainSize: true,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
await tester.tap(find.byKey(anchor), warnIfMissed: false);
|
|
expect(log, <String>[]);
|
|
log.clear();
|
|
|
|
// visible: false, maintain state and animation.
|
|
await tester.pumpWidget(
|
|
boilerPlate(
|
|
SliverVisibility(
|
|
sliver: testChild,
|
|
visible: false,
|
|
maintainState: true,
|
|
maintainAnimation: true,
|
|
),
|
|
),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(Text), findsNothing);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 0.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>['created new state']);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// visible: false, maintain state.
|
|
await tester.pumpWidget(
|
|
boilerPlate(SliverVisibility(sliver: testChild, visible: false, maintainState: true)),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(Text), findsNothing);
|
|
expect(find.text('a false', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 0.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>['created new state']);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// Now we toggle the visibility off and on a few times to make sure that
|
|
// works.
|
|
|
|
// visible: true, maintain state
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild, maintainState: true)));
|
|
expect(find.byType(Text), findsOneWidget);
|
|
expect(find.text('a true'), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paints..paragraph());
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>[]);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['tap']);
|
|
log.clear();
|
|
|
|
// visible: false, maintain state.
|
|
await tester.pumpWidget(
|
|
boilerPlate(SliverVisibility(sliver: testChild, visible: false, maintainState: true)),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(Text), findsNothing);
|
|
expect(find.text('a false', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 0.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a false'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// visible: true, maintain state.
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild, maintainState: true)));
|
|
expect(find.byType(Text), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paints..paragraph());
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>[]);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['tap']);
|
|
log.clear();
|
|
|
|
// visible: false, maintain state.
|
|
await tester.pumpWidget(
|
|
boilerPlate(SliverVisibility(sliver: testChild, visible: false, maintainState: true)),
|
|
);
|
|
expect(find.byType(Text, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(Text), findsNothing);
|
|
expect(find.text('a false', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 0.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a false'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// Same but without maintainState.
|
|
|
|
// visible: false.
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild, visible: false)));
|
|
expect(find.byType(Text, skipOffstage: false), findsNothing);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 0.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// visible: true.
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild)));
|
|
expect(find.byType(Text), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paints..paragraph());
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>['created new state']);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['created new state', 'tap']);
|
|
log.clear();
|
|
|
|
//visible: false.
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild, visible: false)));
|
|
expect(find.byType(Text, skipOffstage: false), findsNothing);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility, skipOffstage: false), paintsNothing);
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 0.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(0));
|
|
expect(log, <String>[]);
|
|
expect(find.byKey(anchor), findsNothing);
|
|
log.clear();
|
|
|
|
// visible: true.
|
|
await tester.pumpWidget(boilerPlate(SliverVisibility(sliver: testChild)));
|
|
expect(find.byType(Text), findsOneWidget);
|
|
expect(find.text('a true', skipOffstage: false), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), findsOneWidget);
|
|
expect(find.byType(SliverVisibility), paints..paragraph());
|
|
renderViewport = tester.renderObject(find.byType(Viewport));
|
|
renderSliver = renderViewport.lastChild!;
|
|
expect(renderSliver.geometry!.scrollExtent, 14.0);
|
|
expect(renderSliver.constraints.crossAxisExtent, 800.0);
|
|
expect(semantics.nodesWith(label: 'a true'), hasLength(1));
|
|
expect(log, <String>['created new state']);
|
|
await tester.tap(find.byKey(anchor));
|
|
expect(log, <String>['created new state', 'tap']);
|
|
log.clear();
|
|
|
|
semantics.dispose();
|
|
});
|
|
}
|