| // 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 'dart:ui'; |
| |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/rendering.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| void main() { |
| testWidgets('Widgets in view update as expected', (WidgetTester tester) async { |
| final Widget widget = View( |
| view: tester.view, |
| child: const TestWidget(), |
| ); |
| |
| await pumpWidgetWithoutViewWrapper( |
| tester: tester, |
| widget: widget, |
| ); |
| |
| expect(find.text('Hello'), findsOneWidget); |
| expect(tester.renderObject<RenderParagraph>(find.byType(Text)).text.toPlainText(), 'Hello'); |
| |
| tester.state<TestWidgetState>(find.byType(TestWidget)).text = 'World'; |
| await tester.pump(); |
| expect(find.text('Hello'), findsNothing); |
| expect(find.text('World'), findsOneWidget); |
| expect(tester.renderObject<RenderParagraph>(find.byType(Text)).text.toPlainText(), 'World'); |
| |
| await pumpWidgetWithoutViewWrapper( |
| tester: tester, |
| widget: ViewCollection( |
| views: <Widget>[widget], |
| ), |
| ); |
| expect(find.text('Hello'), findsNothing); |
| expect(find.text('World'), findsOneWidget); |
| expect(tester.renderObject<RenderParagraph>(find.byType(Text)).text.toPlainText(), 'World'); |
| |
| tester.state<TestWidgetState>(find.byType(TestWidget)).text = 'FooBar'; |
| await pumpWidgetWithoutViewWrapper( |
| tester: tester, |
| widget: widget, |
| ); |
| expect(find.text('World'), findsNothing); |
| expect(find.text('FooBar'), findsOneWidget); |
| expect(tester.renderObject<RenderParagraph>(find.byType(Text)).text.toPlainText(), 'FooBar'); |
| }); |
| |
| testWidgets('Views in ViewCollection update as expected', (WidgetTester tester) async { |
| Iterable<String> renderParagraphTexts() { |
| return tester.renderObjectList<RenderParagraph>(find.byType(Text)).map((RenderParagraph r) => r.text.toPlainText()); |
| } |
| |
| final Key key1 = UniqueKey(); |
| final Key key2 = UniqueKey(); |
| final Widget view1 = View( |
| view: tester.view, |
| child: TestWidget(key: key1), |
| ); |
| final Widget view2 = View( |
| view: FakeView(tester.view), |
| child: TestWidget(key: key2), |
| ); |
| |
| await pumpWidgetWithoutViewWrapper( |
| tester: tester, |
| widget: ViewCollection( |
| views: <Widget>[view1, view2], |
| ), |
| ); |
| |
| expect(find.text('Hello'), findsNWidgets(2)); |
| expect(renderParagraphTexts(), <String>['Hello', 'Hello']); |
| |
| tester.state<TestWidgetState>(find.byKey(key1)).text = 'Guten'; |
| tester.state<TestWidgetState>(find.byKey(key2)).text = 'Tag'; |
| await tester.pump(); |
| expect(find.text('Hello'), findsNothing); |
| expect(find.text('Guten'), findsOneWidget); |
| expect(find.text('Tag'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Guten', 'Tag']); |
| |
| tester.state<TestWidgetState>(find.byKey(key2)).text = 'Abend'; |
| await tester.pump(); |
| expect(find.text('Tag'), findsNothing); |
| expect(find.text('Guten'), findsOneWidget); |
| expect(find.text('Abend'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Guten', 'Abend']); |
| |
| tester.state<TestWidgetState>(find.byKey(key2)).text = 'Morgen'; |
| await pumpWidgetWithoutViewWrapper( |
| tester: tester, |
| widget: ViewCollection( |
| views: <Widget>[view1, ViewCollection(views: <Widget>[view2])], |
| ), |
| ); |
| expect(find.text('Abend'), findsNothing); |
| expect(find.text('Guten'), findsOneWidget); |
| expect(find.text('Morgen'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Guten', 'Morgen']); |
| }); |
| |
| testWidgets('Views in ViewAnchor update as expected', (WidgetTester tester) async { |
| Iterable<String> renderParagraphTexts() { |
| return tester.renderObjectList<RenderParagraph>(find.byType(Text)).map((RenderParagraph r) => r.text.toPlainText()); |
| } |
| |
| final Key insideAnchoredViewKey = UniqueKey(); |
| final Key outsideAnchoredViewKey = UniqueKey(); |
| final Widget view = View( |
| view: FakeView(tester.view), |
| child: TestWidget(key: insideAnchoredViewKey), |
| ); |
| |
| await tester.pumpWidget( |
| ViewAnchor( |
| view: view, |
| child: TestWidget(key: outsideAnchoredViewKey), |
| ), |
| ); |
| |
| expect(find.text('Hello'), findsNWidgets(2)); |
| expect(renderParagraphTexts(), <String>['Hello', 'Hello']); |
| |
| tester.state<TestWidgetState>(find.byKey(outsideAnchoredViewKey)).text = 'Guten'; |
| tester.state<TestWidgetState>(find.byKey(insideAnchoredViewKey)).text = 'Tag'; |
| await tester.pump(); |
| expect(find.text('Hello'), findsNothing); |
| expect(find.text('Guten'), findsOneWidget); |
| expect(find.text('Tag'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Guten', 'Tag']); |
| |
| tester.state<TestWidgetState>(find.byKey(insideAnchoredViewKey)).text = 'Abend'; |
| await tester.pump(); |
| expect(find.text('Tag'), findsNothing); |
| expect(find.text('Guten'), findsOneWidget); |
| expect(find.text('Abend'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Guten', 'Abend']); |
| |
| tester.state<TestWidgetState>(find.byKey(outsideAnchoredViewKey)).text = 'Schönen'; |
| await tester.pump(); |
| expect(find.text('Guten'), findsNothing); |
| expect(find.text('Schönen'), findsOneWidget); |
| expect(find.text('Abend'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Schönen', 'Abend']); |
| |
| tester.state<TestWidgetState>(find.byKey(insideAnchoredViewKey)).text = 'Tag'; |
| await tester.pumpWidget( |
| ViewAnchor( |
| view: ViewCollection(views: <Widget>[view]), |
| child: TestWidget(key: outsideAnchoredViewKey), |
| ), |
| ); |
| await tester.pump(); |
| expect(find.text('Abend'), findsNothing); |
| expect(find.text('Schönen'), findsOneWidget); |
| expect(find.text('Tag'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Schönen', 'Tag']); |
| |
| tester.state<TestWidgetState>(find.byKey(insideAnchoredViewKey)).text = 'Morgen'; |
| await tester.pumpWidget( |
| SizedBox( |
| child: ViewAnchor( |
| view: ViewCollection(views: <Widget>[view]), |
| child: TestWidget(key: outsideAnchoredViewKey), |
| ), |
| ), |
| ); |
| await tester.pump(); |
| expect(find.text('Schönen'), findsNothing); // The `outsideAnchoredViewKey` is not a global key, its state is lost in the move above. |
| expect(find.text('Tag'), findsNothing); |
| expect(find.text('Hello'), findsOneWidget); |
| expect(find.text('Morgen'), findsOneWidget); |
| expect(renderParagraphTexts(), <String>['Hello', 'Morgen']); |
| }); |
| } |
| |
| class TestWidget extends StatefulWidget { |
| const TestWidget({super.key}); |
| |
| @override |
| State<TestWidget> createState() => TestWidgetState(); |
| } |
| |
| class TestWidgetState extends State<TestWidget> { |
| String get text => _text; |
| String _text = 'Hello'; |
| set text(String value) { |
| if (_text == value) { |
| return; |
| } |
| setState(() { |
| _text = value; |
| }); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return Text(text, textDirection: TextDirection.ltr); |
| } |
| } |
| |
| Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, required Widget widget}) { |
| tester.binding.attachRootWidget(widget); |
| tester.binding.scheduleFrame(); |
| return tester.binding.pump(); |
| } |
| |
| class FakeView extends TestFlutterView{ |
| FakeView(FlutterView view, { this.viewId = 100 }) : super( |
| view: view, |
| platformDispatcher: view.platformDispatcher as TestPlatformDispatcher, |
| display: view.display as TestDisplay, |
| ); |
| |
| @override |
| final int viewId; |
| } |