// 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/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('SharedAppData basics', (WidgetTester tester) async { int columnBuildCount = 0; int child1BuildCount = 0; int child2BuildCount = 0; late void Function(BuildContext context) setSharedAppDataValue; await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, child: SharedAppData( child: Builder( builder: (BuildContext context) { columnBuildCount += 1; return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setSharedAppDataValue.call(context); }, child: Column( children: <Widget>[ Builder( builder: (BuildContext context) { child1BuildCount += 1; return Text(SharedAppData.getValue<String, String>(context, 'child1Text', () => 'null')); }, ), Builder( builder: (BuildContext context) { child2BuildCount += 1; return Text(SharedAppData.getValue<String, String>(context, 'child2Text', () => 'null')); } ), ], ), ); }, ), ), ), ); expect(columnBuildCount, 1); expect(child1BuildCount, 1); expect(child2BuildCount, 1); expect(find.text('null').evaluate().length, 2); // SharedAppData.setValue<String, String>(context, 'child1Text', 'child1') // causes the first Text widget to be rebuilt with its text to be // set to 'child1'. Nothing else is rebuilt. setSharedAppDataValue = (BuildContext context) { SharedAppData.setValue<String, String>(context, 'child1Text', 'child1'); }; await tester.tap(find.byType(GestureDetector)); await tester.pump(); expect(columnBuildCount, 1); expect(child1BuildCount, 2); expect(child2BuildCount, 1); expect(find.text('child1'), findsOneWidget); expect(find.text('null'), findsOneWidget); // SharedAppData.setValue<String, String>(context, 'child2Text', 'child1') // causes the second Text widget to be rebuilt with its text to be // set to 'child2'. Nothing else is rebuilt. setSharedAppDataValue = (BuildContext context) { SharedAppData.setValue<String, String>(context, 'child2Text', 'child2'); }; await tester.tap(find.byType(GestureDetector)); await tester.pump(); expect(columnBuildCount, 1); expect(child1BuildCount, 2); expect(child2BuildCount, 2); expect(find.text('child1'), findsOneWidget); expect(find.text('child2'), findsOneWidget); // Resetting a key's value to the same value does not // cause any widgets to be rebuilt. setSharedAppDataValue = (BuildContext context) { SharedAppData.setValue<String, String>(context, 'child1Text', 'child1'); SharedAppData.setValue<String, String>(context, 'child2Text', 'child2'); }; await tester.tap(find.byType(GestureDetector)); await tester.pump(); expect(columnBuildCount, 1); expect(child1BuildCount, 2); expect(child2BuildCount, 2); // More of the same, resetting the values to null.. setSharedAppDataValue = (BuildContext context) { SharedAppData.setValue<String, String>(context, 'child1Text', 'null'); }; await tester.tap(find.byType(GestureDetector)); await tester.pump(); expect(columnBuildCount, 1); expect(child1BuildCount, 3); expect(child2BuildCount, 2); expect(find.text('null'), findsOneWidget); expect(find.text('child2'), findsOneWidget); setSharedAppDataValue = (BuildContext context) { SharedAppData.setValue<String, String>(context, 'child2Text', 'null'); }; await tester.tap(find.byType(GestureDetector)); await tester.pump(); expect(columnBuildCount, 1); expect(child1BuildCount, 3); expect(child2BuildCount, 3); expect(find.text('null').evaluate().length, 2); }); testWidgets('WidgetsApp SharedAppData ', (WidgetTester tester) async { int parentBuildCount = 0; int childBuildCount = 0; await tester.pumpWidget( WidgetsApp( color: const Color(0xff00ff00), builder: (BuildContext context, Widget? child) { parentBuildCount += 1; return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { SharedAppData.setValue<String, String>(context, 'childText', 'child'); }, child: Center( child: Builder( builder: (BuildContext context) { childBuildCount += 1; return Text(SharedAppData.getValue<String, String>(context, 'childText', () => 'null')); }, ), ), ); }, ), ); expect(find.text('null'), findsOneWidget); expect(parentBuildCount, 1); expect(childBuildCount, 1); await tester.tap(find.byType(GestureDetector)); await tester.pump(); expect(parentBuildCount, 1); expect(childBuildCount, 2); expect(find.text('child'), findsOneWidget); }); testWidgets('WidgetsApp SharedAppData Shadowing', (WidgetTester tester) async { int innerTapCount = 0; int outerTapCount = 0; await tester.pumpWidget( WidgetsApp( color: const Color(0xff00ff00), builder: (BuildContext context, Widget? child) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { outerTapCount += 1; SharedAppData.setValue<String, String>(context, 'childText', 'child'); }, child: Center( child: SharedAppData( child: Builder( builder: (BuildContext context) { return GestureDetector( onTap: () { innerTapCount += 1; SharedAppData.setValue<String, String>(context, 'childText', 'child'); }, child: Text(SharedAppData.getValue<String, String>(context, 'childText', () => 'null')), ); }, ), ), ), ); }, ), ); expect(find.text('null'), findsOneWidget); await tester.tapAt(const Offset(10, 10)); await tester.pump(); expect(outerTapCount, 1); expect(innerTapCount, 0); expect(find.text('null'), findsOneWidget); await tester.tap(find.text('null')); await tester.pump(); expect(outerTapCount, 1); expect(innerTapCount, 1); expect(find.text('child'), findsOneWidget); }); }