import 'package:flutter/widgets.dart' hide TypeMatcher; import 'package:flutter_test/flutter_test.dart'; import 'package:matcher/matcher.dart'; import 'package:provider/provider.dart'; Type _typeOf() => T; Matcher throwsProviderNotFound({Type widgetType, Type valueType}) { return throwsA(const TypeMatcher() .having((err) => err.valueType, 'valueType', valueType) .having((err) => err.widgetType, 'widgetType', widgetType)); } void main() { group('MultiProvider', () { test('cloneWithChild works', () { final provider = MultiProvider( providers: [], child: Container(), key: const ValueKey(42), ); final newChild = Container(); final clone = provider.cloneWithChild(newChild); expect(clone.child, newChild); expect(clone.providers, provider.providers); expect(clone.key, provider.key); }); test('throw if providers is null', () { expect( () => MultiProvider(providers: null, child: Container()), throwsAssertionError, ); }); testWidgets('MultiProvider with empty providers returns child', (tester) async { await tester.pumpWidget(const MultiProvider( providers: [], child: Text( 'Foo', textDirection: TextDirection.ltr, ), )); expect(find.text('Foo'), findsOneWidget); }); testWidgets('MultiProvider children can only access parent providers', (tester) async { final k1 = GlobalKey(); final k2 = GlobalKey(); final k3 = GlobalKey(); final p1 = Provider.value(key: k1, value: 42); final p2 = Provider.value(key: k2, value: 'foo'); final p3 = Provider.value(key: k3, value: 44.0); final keyChild = GlobalKey(); await tester.pumpWidget(MultiProvider( providers: [p1, p2, p3], child: Text('Foo', key: keyChild, textDirection: TextDirection.ltr), )); expect(find.text('Foo'), findsOneWidget); // p1 cannot access to p1/p2/p3 expect( () => Provider.of(k1.currentContext), throwsProviderNotFound( valueType: int, widgetType: _typeOf>()), ); expect( () => Provider.of(k1.currentContext), throwsProviderNotFound( valueType: String, widgetType: _typeOf>()), ); expect( () => Provider.of(k1.currentContext), throwsProviderNotFound( valueType: double, widgetType: _typeOf>()), ); // p2 can access only p1 expect(Provider.of(k2.currentContext), 42); expect( () => Provider.of(k2.currentContext), throwsProviderNotFound( valueType: String, widgetType: _typeOf>()), ); expect( () => Provider.of(k2.currentContext), throwsProviderNotFound( valueType: double, widgetType: _typeOf>()), ); // p3 can access both p1 and p2 expect(Provider.of(k3.currentContext), 42); expect(Provider.of(k3.currentContext), 'foo'); expect( () => Provider.of(k3.currentContext), throwsProviderNotFound( valueType: double, widgetType: _typeOf>()), ); // the child can access them all expect(Provider.of(keyChild.currentContext), 42); expect(Provider.of(keyChild.currentContext), 'foo'); expect(Provider.of(keyChild.currentContext), 44); }); }); }