From b02b333b399636c3f582e16b85b4a8f726c825aa Mon Sep 17 00:00:00 2001 From: Remi Rousselet Date: Sun, 30 Oct 2022 12:58:36 +0100 Subject: [PATCH] Add overrideWith (#1839) --- .../auto_dispose.dart | 33 +++++++++ .../src/change_notifier_provider/base.dart | 63 +++++++++++++++++ ...dispose_change_notifier_provider_test.dart | 1 + .../change_notifier_provider_test.dart | 57 +++++++++++++++- packages/riverpod/CHANGELOG.md | 4 +- packages/riverpod/lib/riverpod.dart | 1 + .../lib/src/async_notifier/auto_dispose.dart | 12 ++++ .../async_notifier/auto_dispose_family.dart | 13 ++++ .../riverpod/lib/src/async_notifier/base.dart | 12 ++++ .../lib/src/async_notifier/family.dart | 13 ++++ .../riverpod/lib/src/framework/family.dart | 11 ++- .../lib/src/framework/provider_base.dart | 3 +- .../lib/src/future_provider/auto_dispose.dart | 30 ++++++++- .../lib/src/future_provider/base.dart | 28 +++++++- .../lib/src/notifier/auto_dispose.dart | 12 ++++ .../lib/src/notifier/auto_dispose_family.dart | 13 ++++ packages/riverpod/lib/src/notifier/base.dart | 12 ++++ .../riverpod/lib/src/notifier/family.dart | 13 ++++ .../lib/src/provider/auto_dispose.dart | 28 ++++++++ packages/riverpod/lib/src/provider/base.dart | 61 +++++++++++++++++ .../state_notifier_provider/auto_dispose.dart | 33 +++++++++ .../lib/src/state_notifier_provider/base.dart | 29 ++++++++ .../lib/src/state_provider/auto_dispose.dart | 28 ++++++++ .../riverpod/lib/src/state_provider/base.dart | 28 ++++++++ .../lib/src/stream_provider/auto_dispose.dart | 28 ++++++++ .../lib/src/stream_provider/base.dart | 26 +++++++ .../framework/provider_container_test.dart | 1 + .../riverpod/test/framework/scope_test.dart | 2 + .../async_notifier/async_notifier_test.dart | 45 +++++++++++++ .../auto_dispose_future_provider_test.dart | 1 + .../future_provider/future_provider_test.dart | 39 +++++++++++ .../providers/notifier/notifier_test.dart | 44 ++++++++++++ .../provider/auto_dispose_provider_test.dart | 2 + .../providers/provider/provider_test.dart | 37 ++++++++++ ..._dispose_state_notifier_provider_test.dart | 2 + .../state_notifier_provider_test.dart | 56 ++++++++++++++++ .../state_provider_auto_dispose_test.dart | 1 + .../state_provider/state_provider_test.dart | 41 ++++++++++++ .../auto_dispose_stream_provider_test.dart | 1 + .../stream_provider/stream_provider_test.dart | 67 ++++++++++++++++++- 40 files changed, 922 insertions(+), 9 deletions(-) diff --git a/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart b/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart index d01e55cb9..27ab25214 100644 --- a/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart +++ b/packages/flutter_riverpod/lib/src/change_notifier_provider/auto_dispose.dart @@ -40,6 +40,20 @@ class AutoDisposeChangeNotifierProvider @override late final Refreshable notifier = _notifier(this); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: AutoDisposeChangeNotifierProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [AutoDisposeChangeNotifierProvider]. @@ -70,4 +84,23 @@ class AutoDisposeChangeNotifierProviderFamily ref, + Arg arg, + ) + create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => AutoDisposeChangeNotifierProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart b/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart index 1079f1be6..9986f5aa8 100644 --- a/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart +++ b/packages/flutter_riverpod/lib/src/change_notifier_provider/base.dart @@ -110,6 +110,53 @@ class ChangeNotifierProvider @override late final AlwaysAliveRefreshable notifier = _notifier(this); + + /// {@template riverpod.overridewith} + /// Override the provider with a new initialization function. + /// + /// This will also disable the auto-scoping mechanism, meaning that if the + /// overridden provider specified `dependencies`, it will have no effect. + /// + /// The override must not specify a `dependencies`. + /// + /// Some common use-cases are: + /// - testing, by replacing a service with a fake implementation, or to reach + /// a very specific state easily. + /// - multiple environments, by changing the implementation of a class + /// based on the platform or other parameters. + /// + /// This function should be used in combination with `ProviderScope.overrides` + /// or `ProviderContainer.overrides`: + /// + /// ```dart + /// final myService = Provider((ref) => MyService()); + /// + /// runApp( + /// ProviderScope( + /// overrides: [ + /// // Replace the implementation of the provider with a different one + /// myService.overrideWithProvider((ref) { + /// ref.watch('other'); + /// return MyFakeService(), + /// })), + /// ], + /// child: MyApp(), + /// ), + /// ); + /// ``` + /// {@endtemplate} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: ChangeNotifierProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [ChangeNotifierProvider]. @@ -187,4 +234,20 @@ class ChangeNotifierProviderFamily super.name, super.dependencies, }) : super(providerFactory: ChangeNotifierProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + NotifierT Function(ChangeNotifierProviderRef ref, Arg arg) + create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => ChangeNotifierProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart b/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart index 466a1094e..18ed4e34e 100644 --- a/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart +++ b/packages/flutter_riverpod/test/providers/change_notifier/auto_dispose_change_notifier_provider_test.dart @@ -118,6 +118,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use provider.overrideWithProvider( ChangeNotifierProvider.autoDispose((ref) => ValueNotifier(42)), ), diff --git a/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart b/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart index cc54e6cd2..3e9f7986f 100644 --- a/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart +++ b/packages/flutter_riverpod/test/providers/change_notifier/change_notifier_provider_test.dart @@ -1,4 +1,4 @@ -// ignore_for_file: invalid_use_of_internal_member +// ignore_for_file: invalid_use_of_internal_member, avoid_types_on_closure_parameters import 'package:flutter/widgets.dart' hide Listener; import 'package:flutter_riverpod/src/internals.dart'; @@ -8,6 +8,58 @@ import 'package:mockito/mockito.dart'; import '../../utils.dart'; void main() { + test('supports overrideWith', () { + final provider = + ChangeNotifierProvider>((ref) => ValueNotifier(0)); + final autoDispose = ChangeNotifierProvider.autoDispose>( + (ref) => ValueNotifier(0), + ); + + final container = createContainer( + overrides: [ + provider.overrideWith( + (ChangeNotifierProviderRef> ref) => + ValueNotifier(42), + ), + autoDispose.overrideWith( + (AutoDisposeChangeNotifierProviderRef> ref) => + ValueNotifier(84), + ), + ], + ); + + expect(container.read(provider).value, 42); + expect(container.read(autoDispose).value, 84); + }); + + test('supports family overrideWith', () { + final family = ChangeNotifierProvider.family, int>( + (ref, arg) => ValueNotifier('0 $arg'), + ); + final autoDisposeFamily = + ChangeNotifierProvider.autoDispose.family, int>( + (ref, arg) => ValueNotifier('0 $arg'), + ); + final container = createContainer( + overrides: [ + family.overrideWith( + (ChangeNotifierProviderRef> ref, int arg) => + ValueNotifier('42 $arg'), + ), + autoDisposeFamily.overrideWith( + ( + AutoDisposeChangeNotifierProviderRef> ref, + int arg, + ) => + ValueNotifier('84 $arg'), + ), + ], + ); + + expect(container.read(family(10)).value, '42 10'); + expect(container.read(autoDisposeFamily(10)).value, '84 10'); + }); + test('ref.listenSelf listens to state changes', () { final listener = Listener>(); final container = createContainer(); @@ -141,6 +193,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use provider.overrideWithProvider( ChangeNotifierProvider((ref) => ValueNotifier(42)), ), @@ -363,6 +416,7 @@ void main() { final notifier2 = TestNotifier(); final container = createContainer( overrides: [ + // ignore: deprecated_member_use provider.overrideWithProvider(ChangeNotifierProvider((_) => notifier)), ], ); @@ -382,6 +436,7 @@ void main() { expect(callCount, 1); container.updateOverrides([ + // ignore: deprecated_member_use provider.overrideWithProvider(ChangeNotifierProvider((_) => notifier2)), ]); diff --git a/packages/riverpod/CHANGELOG.md b/packages/riverpod/CHANGELOG.md index 08b02f0e0..149962c8d 100644 --- a/packages/riverpod/CHANGELOG.md +++ b/packages/riverpod/CHANGELOG.md @@ -1,7 +1,9 @@ ## [Unreleased minor] -- Deprecate `StateProvider.state` +- Added `provider.overrideWith((ref) => state`) +- Deprecated `StateProvider.state` Instead, use either `ref.watch(stateProvider)` or `ref.read(stateProvider.notifier).state =` +- Deprecated `provider.overrideWithProvider`. Instead use `provider.overrideWith` - Added `Ref.notifyListeners()` to forcibly notify dependents. This can be useful for mutable state. - Added `@useResult` to `Ref.refresh`/`WidgetRef.refresh` diff --git a/packages/riverpod/lib/riverpod.dart b/packages/riverpod/lib/riverpod.dart index b7cd54ae3..43e87c961 100644 --- a/packages/riverpod/lib/riverpod.dart +++ b/packages/riverpod/lib/riverpod.dart @@ -24,6 +24,7 @@ export 'src/framework.dart' FamilyCreate, AsyncSelector, FamilyBase, + FamilyOverrideImpl, AutoDisposeProviderElementMixin, FamilyOverride, NotifierFamilyBase, diff --git a/packages/riverpod/lib/src/async_notifier/auto_dispose.dart b/packages/riverpod/lib/src/async_notifier/auto_dispose.dart index 45f2050e7..e61dcb0ff 100644 --- a/packages/riverpod/lib/src/async_notifier/auto_dispose.dart +++ b/packages/riverpod/lib/src/async_notifier/auto_dispose.dart @@ -74,6 +74,18 @@ class AutoDisposeAsyncNotifierProviderImpl< FutureOr runNotifierBuild(AsyncNotifierBase notifier) { return (notifier as AutoDisposeAsyncNotifier).build(); } + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return ProviderOverride( + origin: this, + override: AutoDisposeAsyncNotifierProviderImpl( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [AutoDisposeAsyncNotifierProvider]. diff --git a/packages/riverpod/lib/src/async_notifier/auto_dispose_family.dart b/packages/riverpod/lib/src/async_notifier/auto_dispose_family.dart index 19a49c53c..1b73542de 100644 --- a/packages/riverpod/lib/src/async_notifier/auto_dispose_family.dart +++ b/packages/riverpod/lib/src/async_notifier/auto_dispose_family.dart @@ -76,4 +76,17 @@ class AutoDisposeAsyncNotifierProviderFamily< super.name, super.dependencies, }) : super(providerFactory: AutoDisposeFamilyAsyncNotifierProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return FamilyOverrideImpl, Arg, + AutoDisposeFamilyAsyncNotifierProvider>( + this, + (arg) => AutoDisposeFamilyAsyncNotifierProvider( + create, + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/async_notifier/base.dart b/packages/riverpod/lib/src/async_notifier/base.dart index 2b5bdf0d0..e150412a3 100644 --- a/packages/riverpod/lib/src/async_notifier/base.dart +++ b/packages/riverpod/lib/src/async_notifier/base.dart @@ -99,6 +99,18 @@ class AsyncNotifierProviderImpl, T> FutureOr runNotifierBuild(AsyncNotifierBase notifier) { return (notifier as AsyncNotifier).build(); } + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return ProviderOverride( + origin: this, + override: AsyncNotifierProviderImpl( + create, + from: from, + argument: argument, + ), + ); + } } /// A mixin shared by [AsyncNotifierProvider] and [FutureProvider] for dealing with diff --git a/packages/riverpod/lib/src/async_notifier/family.dart b/packages/riverpod/lib/src/async_notifier/family.dart index 3acd17072..1a66c80ce 100644 --- a/packages/riverpod/lib/src/async_notifier/family.dart +++ b/packages/riverpod/lib/src/async_notifier/family.dart @@ -86,4 +86,17 @@ class AsyncNotifierProviderFamily, super.name, super.dependencies, }) : super(providerFactory: AsyncNotifierFamilyProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return FamilyOverrideImpl, Arg, + AsyncNotifierFamilyProvider>( + this, + (arg) => AsyncNotifierFamilyProvider( + create, + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/framework/family.dart b/packages/riverpod/lib/src/framework/family.dart index c3ead78f1..c2c3f7988 100644 --- a/packages/riverpod/lib/src/framework/family.dart +++ b/packages/riverpod/lib/src/framework/family.dart @@ -41,7 +41,7 @@ mixin _FamilyMixin> Override overrideWithProvider( FamilyProvider Function(Arg argument) override, ) { - return _FamilyOverride(this, override); + return FamilyOverrideImpl(this, override); } @visibleForOverriding @@ -73,13 +73,18 @@ abstract class FamilyOverride implements Override { ProviderBase getProviderOverride(ProviderBase provider); } -class _FamilyOverride> +/// An [Override] for families +@internal +class FamilyOverrideImpl> implements FamilyOverride { - _FamilyOverride(this.overriddenFamily, this._newCreate); + /// An [Override] for families + // ignore: library_private_types_in_public_api + FamilyOverrideImpl(this.overriddenFamily, this._newCreate); final FamilyProvider Function(Arg arg) _newCreate; @override + // ignore: library_private_types_in_public_api final _FamilyMixin overriddenFamily; @visibleForOverriding diff --git a/packages/riverpod/lib/src/framework/provider_base.dart b/packages/riverpod/lib/src/framework/provider_base.dart index d12668586..d3bc7a24c 100644 --- a/packages/riverpod/lib/src/framework/provider_base.dart +++ b/packages/riverpod/lib/src/framework/provider_base.dart @@ -249,7 +249,7 @@ mixin OverrideWithValueMixin on ProviderBase { } } -/// A mixin to add [overrideWithProvider] capability to providers. +/// A mixin to add `overrideWithProvider` capability to providers. extension OverrideWithProviderExtension> on ProviderType { /// {@template riverpod.overridewithprovider} @@ -288,6 +288,7 @@ extension OverrideWithProviderExtension extends _FutureProviderBase /// {@macro riverpod.family} static const family = AutoDisposeFutureProviderFamily.new; - final FutureOr Function(AutoDisposeFutureProviderRef ref) _createFn; + final Create, AutoDisposeFutureProviderRef> _createFn; @override FutureOr _create(AutoDisposeFutureProviderElement ref) => @@ -35,6 +35,20 @@ class AutoDisposeFutureProvider extends _FutureProviderBase @override late final Refreshable> future = _future(this); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create, AutoDisposeFutureProviderRef> create, + ) { + return ProviderOverride( + origin: this, + override: AutoDisposeFutureProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The [ProviderElementBase] of [AutoDisposeFutureProvider] @@ -60,4 +74,18 @@ class AutoDisposeFutureProviderFamily extends AutoDisposeFamilyBase< super.name, super.dependencies, }) : super(providerFactory: AutoDisposeFutureProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + FutureOr Function(AutoDisposeFutureProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl, Arg, AutoDisposeFutureProvider>( + this, + (arg) => AutoDisposeFutureProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/future_provider/base.dart b/packages/riverpod/lib/src/future_provider/base.dart index 3a23a1222..15c2c94cf 100644 --- a/packages/riverpod/lib/src/future_provider/base.dart +++ b/packages/riverpod/lib/src/future_provider/base.dart @@ -33,7 +33,7 @@ class FutureProvider extends _FutureProviderBase /// {@macro riverpod.family} static const family = FutureProviderFamilyBuilder(); - final FutureOr Function(FutureProviderRef ref) _createFn; + final Create, FutureProviderRef> _createFn; @override late final AlwaysAliveRefreshable> future = _future(this); @@ -43,6 +43,18 @@ class FutureProvider extends _FutureProviderBase @override FutureProviderElement createElement() => FutureProviderElement._(this); + + /// {@macro riverpod.overridewith} + Override overrideWith(Create, FutureProviderRef> create) { + return ProviderOverride( + origin: this, + override: FutureProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of a [FutureProvider] @@ -82,4 +94,18 @@ class FutureProviderFamily extends FamilyBase, super.name, super.dependencies, }) : super(providerFactory: FutureProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + FutureOr Function(FutureProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl, Arg, FutureProvider>( + this, + (arg) => FutureProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/notifier/auto_dispose.dart b/packages/riverpod/lib/src/notifier/auto_dispose.dart index 8b8753262..d4b4b75de 100644 --- a/packages/riverpod/lib/src/notifier/auto_dispose.dart +++ b/packages/riverpod/lib/src/notifier/auto_dispose.dart @@ -68,6 +68,18 @@ class AutoDisposeNotifierProviderImpl, T> T runNotifierBuild(NotifierBase notifier) { return (notifier as AutoDisposeNotifier).build(); } + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return ProviderOverride( + origin: this, + override: AutoDisposeNotifierProviderImpl( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [AutoDisposeNotifierProvider] diff --git a/packages/riverpod/lib/src/notifier/auto_dispose_family.dart b/packages/riverpod/lib/src/notifier/auto_dispose_family.dart index adfb632fc..bbd59dca7 100644 --- a/packages/riverpod/lib/src/notifier/auto_dispose_family.dart +++ b/packages/riverpod/lib/src/notifier/auto_dispose_family.dart @@ -67,4 +67,17 @@ class AutoDisposeNotifierProviderFamily< super.name, super.dependencies, }) : super(providerFactory: AutoDisposeFamilyNotifierProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return FamilyOverrideImpl>( + this, + (arg) => AutoDisposeFamilyNotifierProvider( + create, + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/notifier/base.dart b/packages/riverpod/lib/src/notifier/base.dart index 9660bdba8..67e9cac39 100644 --- a/packages/riverpod/lib/src/notifier/base.dart +++ b/packages/riverpod/lib/src/notifier/base.dart @@ -129,6 +129,18 @@ class NotifierProviderImpl, T> T runNotifierBuild(NotifierBase notifier) { return (notifier as Notifier).build(); } + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return ProviderOverride( + origin: this, + override: NotifierProviderImpl( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [NotifierProvider]. diff --git a/packages/riverpod/lib/src/notifier/family.dart b/packages/riverpod/lib/src/notifier/family.dart index 921cbc941..8f6d08d04 100644 --- a/packages/riverpod/lib/src/notifier/family.dart +++ b/packages/riverpod/lib/src/notifier/family.dart @@ -73,4 +73,17 @@ class NotifierProviderFamily, T, Arg> super.name, super.dependencies, }) : super(providerFactory: NotifierFamilyProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWithNotifier(NotifierT Function() create) { + return FamilyOverrideImpl>( + this, + (arg) => NotifierFamilyProvider( + create, + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/provider/auto_dispose.dart b/packages/riverpod/lib/src/provider/auto_dispose.dart index 62dea24b2..7b5cb2343 100644 --- a/packages/riverpod/lib/src/provider/auto_dispose.dart +++ b/packages/riverpod/lib/src/provider/auto_dispose.dart @@ -28,6 +28,20 @@ class AutoDisposeProvider extends InternalProvider { AutoDisposeProviderElement createElement() { return AutoDisposeProviderElement._(this); } + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: AutoDisposeProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [AutoDisposeProvider] @@ -48,4 +62,18 @@ class AutoDisposeProviderFamily extends AutoDisposeFamilyBase< super.name, super.dependencies, }) : super(providerFactory: AutoDisposeProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + R Function(AutoDisposeProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => AutoDisposeProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/provider/base.dart b/packages/riverpod/lib/src/provider/base.dart index 1997f055b..f94fca684 100644 --- a/packages/riverpod/lib/src/provider/base.dart +++ b/packages/riverpod/lib/src/provider/base.dart @@ -41,6 +41,53 @@ class Provider extends InternalProvider @override ProviderElement createElement() => ProviderElement._(this); + + /// {@template riverpod.overridewith} + /// Override the provider with a new initialization function. + /// + /// This will also disable the auto-scoping mechanism, meaning that if the + /// overridden provider specified `dependencies`, it will have no effect. + /// + /// The override must not specify a `dependencies`. + /// + /// Some common use-cases are: + /// - testing, by replacing a service with a fake implementation, or to reach + /// a very specific state easily. + /// - multiple environments, by changing the implementation of a class + /// based on the platform or other parameters. + /// + /// This function should be used in combination with `ProviderScope.overrides` + /// or `ProviderContainer.overrides`: + /// + /// ```dart + /// final myService = Provider((ref) => MyService()); + /// + /// runApp( + /// ProviderScope( + /// overrides: [ + /// // Replace the implementation of the provider with a different one + /// myService.overrideWithProvider((ref) { + /// ref.watch('other'); + /// return MyFakeService(), + /// })), + /// ], + /// child: MyApp(), + /// ), + /// ); + /// ``` + /// {@endtemplate} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: Provider( + create, + from: from, + argument: argument, + ), + ); + } } /// {@template riverpod.provider} @@ -286,4 +333,18 @@ class ProviderFamily super.name, super.dependencies, }) : super(providerFactory: Provider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + R Function(ProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => Provider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart b/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart index 156f17062..1ce56be1b 100644 --- a/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart +++ b/packages/riverpod/lib/src/state_notifier_provider/auto_dispose.dart @@ -38,6 +38,20 @@ class AutoDisposeStateNotifierProvider, T> @override late final Refreshable notifier = _notifier(this); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: AutoDisposeStateNotifierProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [AutoDisposeStateNotifierProvider]. @@ -67,4 +81,23 @@ class AutoDisposeStateNotifierProviderFamily, super.name, super.dependencies, }) : super(providerFactory: AutoDisposeStateNotifierProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + NotifierT Function( + AutoDisposeStateNotifierProviderRef ref, + Arg arg, + ) + create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => AutoDisposeStateNotifierProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/state_notifier_provider/base.dart b/packages/riverpod/lib/src/state_notifier_provider/base.dart index ebfb8ac8d..f7ea4a213 100644 --- a/packages/riverpod/lib/src/state_notifier_provider/base.dart +++ b/packages/riverpod/lib/src/state_notifier_provider/base.dart @@ -107,6 +107,20 @@ class StateNotifierProvider, T> @override late final AlwaysAliveRefreshable notifier = _notifier(this); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: StateNotifierProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [StateNotifierProvider]. @@ -182,4 +196,19 @@ class StateNotifierProviderFamily, T, Arg> super.name, super.dependencies, }) : super(providerFactory: StateNotifierProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + NotifierT Function(StateNotifierProviderRef ref, Arg arg) + create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => StateNotifierProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/state_provider/auto_dispose.dart b/packages/riverpod/lib/src/state_provider/auto_dispose.dart index a68e180ce..2239b4447 100644 --- a/packages/riverpod/lib/src/state_provider/auto_dispose.dart +++ b/packages/riverpod/lib/src/state_provider/auto_dispose.dart @@ -39,6 +39,20 @@ class AutoDisposeStateProvider extends _StateProviderBase { ) @override late final Refreshable> state = _state(this); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: AutoDisposeStateProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [StateProvider]. @@ -59,4 +73,18 @@ class AutoDisposeStateProviderFamily extends AutoDisposeFamilyBase< super.name, super.dependencies, }) : super(providerFactory: AutoDisposeStateProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + R Function(AutoDisposeStateProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => AutoDisposeStateProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/state_provider/base.dart b/packages/riverpod/lib/src/state_provider/base.dart index fdb665fc8..7043e061c 100644 --- a/packages/riverpod/lib/src/state_provider/base.dart +++ b/packages/riverpod/lib/src/state_provider/base.dart @@ -78,6 +78,20 @@ class StateProvider extends _StateProviderBase ) @override late final AlwaysAliveRefreshable> state = _state(this); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create> create, + ) { + return ProviderOverride( + origin: this, + override: StateProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [StateProvider]. @@ -149,4 +163,18 @@ class StateProviderFamily super.name, super.dependencies, }) : super(providerFactory: StateProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + R Function(StateProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl>( + this, + (arg) => StateProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/stream_provider/auto_dispose.dart b/packages/riverpod/lib/src/stream_provider/auto_dispose.dart index c070874df..28677a720 100644 --- a/packages/riverpod/lib/src/stream_provider/auto_dispose.dart +++ b/packages/riverpod/lib/src/stream_provider/auto_dispose.dart @@ -36,6 +36,20 @@ class AutoDisposeStreamProvider extends _StreamProviderBase @override late final Refreshable> stream = _stream(this); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Create, AutoDisposeStreamProviderRef> create, + ) { + return ProviderOverride( + origin: this, + override: AutoDisposeStreamProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [AutoDisposeStreamProvider]. @@ -61,4 +75,18 @@ class AutoDisposeStreamProviderFamily extends AutoDisposeFamilyBase< super.name, super.dependencies, }) : super(providerFactory: AutoDisposeStreamProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Stream Function(AutoDisposeStreamProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl, Arg, AutoDisposeStreamProvider>( + this, + (arg) => AutoDisposeStreamProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/lib/src/stream_provider/base.dart b/packages/riverpod/lib/src/stream_provider/base.dart index f35eb2719..976078df1 100644 --- a/packages/riverpod/lib/src/stream_provider/base.dart +++ b/packages/riverpod/lib/src/stream_provider/base.dart @@ -102,6 +102,18 @@ class StreamProvider extends _StreamProviderBase @override StreamProviderElement createElement() => StreamProviderElement._(this); + + /// {@macro riverpod.overridewith} + Override overrideWith(Create, StreamProviderRef> create) { + return ProviderOverride( + origin: this, + override: StreamProvider( + create, + from: from, + argument: argument, + ), + ); + } } /// The element of [StreamProvider]. @@ -249,4 +261,18 @@ class StreamProviderFamily extends FamilyBase, super.name, super.dependencies, }) : super(providerFactory: StreamProvider.new); + + /// {@macro riverpod.overridewith} + Override overrideWith( + Stream Function(StreamProviderRef ref, Arg arg) create, + ) { + return FamilyOverrideImpl, Arg, StreamProvider>( + this, + (arg) => StreamProvider( + (ref) => create(ref, arg), + from: from, + argument: arg, + ), + ); + } } diff --git a/packages/riverpod/test/framework/provider_container_test.dart b/packages/riverpod/test/framework/provider_container_test.dart index 4aab3b0b1..f602e8edb 100644 --- a/packages/riverpod/test/framework/provider_container_test.dart +++ b/packages/riverpod/test/framework/provider_container_test.dart @@ -100,6 +100,7 @@ void main() { final container = createContainer( overrides: [ + // ignore: deprecated_member_use_from_same_package fooProvider.overrideWithProvider( Provider((ref) => Bar()), ), diff --git a/packages/riverpod/test/framework/scope_test.dart b/packages/riverpod/test/framework/scope_test.dart index 63e347483..9532cacb7 100644 --- a/packages/riverpod/test/framework/scope_test.dart +++ b/packages/riverpod/test/framework/scope_test.dart @@ -755,6 +755,7 @@ final b = Provider( final a = Provider((ref) => 0); expect( + // ignore: deprecated_member_use_from_same_package () => provider.overrideWithProvider( Provider((ref) => 0, dependencies: [a]), ), @@ -771,6 +772,7 @@ final b = Provider( final root = createContainer( overrides: [ b.overrideWithValue(21), + // ignore: deprecated_member_use_from_same_package c.overrideWithProvider(Provider((ref) => ref.watch(another) + 10)), ], ); diff --git a/packages/riverpod/test/providers/async_notifier/async_notifier_test.dart b/packages/riverpod/test/providers/async_notifier/async_notifier_test.dart index d70334c03..847320014 100644 --- a/packages/riverpod/test/providers/async_notifier/async_notifier_test.dart +++ b/packages/riverpod/test/providers/async_notifier/async_notifier_test.dart @@ -805,6 +805,51 @@ void main() { }); } + test('supports overrideWithNotifier', () { + final provider = AsyncNotifierProvider, int>( + () => AsyncTestNotifier((ref) => 0), + ); + final autoDispose = AsyncNotifierProvider.autoDispose< + AutoDisposeAsyncTestNotifier, int>( + () => AutoDisposeAsyncTestNotifier((ref) => 0), + ); + final container = createContainer( + overrides: [ + provider.overrideWithNotifier(() => AsyncTestNotifier((ref) => 42)), + autoDispose.overrideWithNotifier( + () => AutoDisposeAsyncTestNotifier((ref) => 84), + ), + ], + ); + + expect(container.read(provider).value, 42); + expect(container.read(autoDispose).value, 84); + }); + + test('supports family overrideWith', () { + final family = + AsyncNotifierProvider.family, int, int>( + () => AsyncTestNotifierFamily((ref) => 0), + ); + final autoDisposeFamily = AsyncNotifierProvider.autoDispose + .family, int, int>( + () => AutoDisposeAsyncTestNotifierFamily((ref) => 0), + ); + final container = createContainer( + overrides: [ + family.overrideWithNotifier( + () => AsyncTestNotifierFamily((ref) => 42), + ), + autoDisposeFamily.overrideWithNotifier( + () => AutoDisposeAsyncTestNotifierFamily((ref) => 84), + ), + ], + ); + + expect(container.read(family(10)).value, 42); + expect(container.read(autoDisposeFamily(10)).value, 84); + }); + group('AutoDispose variant', () { test('can watch autoDispose providers', () { final dep = Provider.autoDispose((ref) => 0); diff --git a/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart b/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart index c3144bcc6..7a779f78a 100644 --- a/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart +++ b/packages/riverpod/test/providers/future_provider/auto_dispose_future_provider_test.dart @@ -249,6 +249,7 @@ void main() { parent: root, overrides: [ provider + // ignore: deprecated_member_use_from_same_package .overrideWithProvider(FutureProvider.autoDispose((ref) => 42)), ], ); diff --git a/packages/riverpod/test/providers/future_provider/future_provider_test.dart b/packages/riverpod/test/providers/future_provider/future_provider_test.dart index 2b2668634..4b01ccec5 100644 --- a/packages/riverpod/test/providers/future_provider/future_provider_test.dart +++ b/packages/riverpod/test/providers/future_provider/future_provider_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_types_on_closure_parameters + import 'dart:async'; import 'package:mockito/mockito.dart'; @@ -7,6 +9,42 @@ import 'package:test/test.dart'; import '../../utils.dart'; void main() { + test('supports overrideWith', () { + final provider = FutureProvider((ref) => 0); + final autoDispose = FutureProvider.autoDispose((ref) => 0); + final container = createContainer( + overrides: [ + provider.overrideWith((FutureProviderRef ref) => 42), + autoDispose.overrideWith( + (AutoDisposeFutureProviderRef ref) => 84, + ), + ], + ); + + expect(container.read(provider).value, 42); + expect(container.read(autoDispose).value, 84); + }); + + test('supports family overrideWith', () { + final family = FutureProvider.family((ref, arg) => '0 $arg'); + final autoDisposeFamily = FutureProvider.autoDispose.family( + (ref, arg) => '0 $arg', + ); + final container = createContainer( + overrides: [ + family.overrideWith( + (FutureProviderRef ref, int arg) => '42 $arg', + ), + autoDisposeFamily.overrideWith( + (AutoDisposeFutureProviderRef ref, int arg) => '84 $arg', + ), + ], + ); + + expect(container.read(family(10)).value, '42 10'); + expect(container.read(autoDisposeFamily(10)).value, '84 10'); + }); + test('Emits AsyncLoading before the create function is executed', () async { final container = createContainer(); late AsyncValue state; @@ -329,6 +367,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider(FutureProvider((ref) async => 42)), ], ); diff --git a/packages/riverpod/test/providers/notifier/notifier_test.dart b/packages/riverpod/test/providers/notifier/notifier_test.dart index 7321b2df2..4be50758e 100644 --- a/packages/riverpod/test/providers/notifier/notifier_test.dart +++ b/packages/riverpod/test/providers/notifier/notifier_test.dart @@ -350,6 +350,50 @@ void main() { } } + test('supports overrideWithNotifier', () { + final provider = NotifierProvider, int>( + () => TestNotifier((ref) => 0), + ); + final autoDispose = + NotifierProvider.autoDispose, int>( + () => AutoDisposeTestNotifier((ref) => 0), + ); + final container = createContainer( + overrides: [ + provider.overrideWithNotifier(() => TestNotifier((ref) => 42)), + autoDispose.overrideWithNotifier( + () => AutoDisposeTestNotifier((ref) => 84), + ), + ], + ); + + expect(container.read(provider), 42); + expect(container.read(autoDispose), 84); + }); + + test('supports family overrideWith', () { + final family = NotifierProvider.family, int, int>( + () => TestNotifierFamily((ref) => 0), + ); + final autoDisposeFamily = NotifierProvider.autoDispose + .family, int, int>( + () => AutoDisposeTestNotifierFamily((ref) => 0), + ); + final container = createContainer( + overrides: [ + family.overrideWithNotifier( + () => TestNotifierFamily((ref) => 42), + ), + autoDisposeFamily.overrideWithNotifier( + () => AutoDisposeTestNotifierFamily((ref) => 84), + ), + ], + ); + + expect(container.read(family(10)), 42); + expect(container.read(autoDisposeFamily(10)), 84); + }); + group('modifiers', () { void canBeAssignedToAlwaysAliveRefreshable( AlwaysAliveRefreshable provider, diff --git a/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart b/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart index c73543bd7..c18eaf942 100644 --- a/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart +++ b/packages/riverpod/test/providers/provider/auto_dispose_provider_test.dart @@ -151,6 +151,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider(Provider.autoDispose((ref) => 42)), ], ); @@ -170,6 +171,7 @@ void main() { }); final container = createContainer( overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider(override), ], ); diff --git a/packages/riverpod/test/providers/provider/provider_test.dart b/packages/riverpod/test/providers/provider/provider_test.dart index 14c77e445..b1740cddd 100644 --- a/packages/riverpod/test/providers/provider/provider_test.dart +++ b/packages/riverpod/test/providers/provider/provider_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_types_on_closure_parameters + import 'package:mockito/mockito.dart'; import 'package:riverpod/riverpod.dart'; import 'package:test/test.dart'; @@ -6,6 +8,40 @@ import '../../utils.dart'; void main() { group('Provider', () { + test('supports overrideWith', () { + final provider = Provider((ref) => 0); + final autoDispose = Provider.autoDispose((ref) => 0); + final container = createContainer( + overrides: [ + provider.overrideWith((ProviderRef ref) => 42), + autoDispose.overrideWith( + (AutoDisposeProviderRef ref) => 84, + ), + ], + ); + + expect(container.read(provider), 42); + expect(container.read(autoDispose), 84); + }); + + test('supports family overrideWith', () { + final family = Provider.family((ref, arg) => '0 $arg'); + final autoDisposeFamily = Provider.autoDispose.family( + (ref, arg) => '0 $arg', + ); + final container = createContainer( + overrides: [ + family.overrideWith((ProviderRef ref, int arg) => '42 $arg'), + autoDisposeFamily.overrideWith( + (AutoDisposeProviderRef ref, int arg) => '84 $arg', + ), + ], + ); + + expect(container.read(family(10)), '42 10'); + expect(container.read(autoDisposeFamily(10)), '84 10'); + }); + test('can be refreshed', () async { var result = 0; final container = createContainer(); @@ -167,6 +203,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider(Provider((ref) => 42)), ], ); diff --git a/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart b/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart index f4ce1a1fe..3d9ae9c8a 100644 --- a/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart +++ b/packages/riverpod/test/providers/state_notifier_provider/auto_dispose_state_notifier_provider_test.dart @@ -276,6 +276,7 @@ void main() { final notifier2 = TestNotifier(21); final container = createContainer( overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StateNotifierProvider.autoDispose((_) { return notifier; @@ -297,6 +298,7 @@ void main() { verifyOnly(listener, listener(42, 43)); container.updateOverrides([ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StateNotifierProvider.autoDispose((_) { return notifier2; diff --git a/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart b/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart index 848150da4..36be0c4e7 100644 --- a/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart +++ b/packages/riverpod/test/providers/state_notifier_provider/state_notifier_provider_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_types_on_closure_parameters + import 'package:mockito/mockito.dart'; import 'package:riverpod/riverpod.dart'; import 'package:test/test.dart'; @@ -5,6 +7,57 @@ import 'package:test/test.dart'; import '../../utils.dart'; void main() { + test('supports overrideWith', () { + final provider = StateNotifierProvider( + (ref) => TestNotifier(), + ); + final autoDispose = StateNotifierProvider.autoDispose( + (ref) => TestNotifier(), + ); + final container = createContainer( + overrides: [ + provider.overrideWith( + (StateNotifierProviderRef ref) => TestNotifier(42), + ), + autoDispose.overrideWith( + (AutoDisposeStateNotifierProviderRef ref) => + TestNotifier(84), + ), + ], + ); + + expect(container.read(provider), 42); + expect(container.read(autoDispose), 84); + }); + + test('supports family overrideWith', () { + final family = StateNotifierProvider.family( + (ref, arg) => TestNotifier(0 + arg), + ); + final autoDisposeFamily = + StateNotifierProvider.autoDispose.family( + (ref, arg) => TestNotifier(0 + arg), + ); + final container = createContainer( + overrides: [ + family.overrideWith( + (StateNotifierProviderRef ref, int arg) => + TestNotifier(42 + arg), + ), + autoDisposeFamily.overrideWith( + ( + AutoDisposeStateNotifierProviderRef ref, + int arg, + ) => + TestNotifier(84 + arg), + ), + ], + ); + + expect(container.read(family(10)), 52); + expect(container.read(autoDisposeFamily(10)), 94); + }); + test( 'on refresh, does not notify listeners if the new value is identical to the previous one', () { @@ -162,6 +215,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StateNotifierProvider.autoDispose, int>( (ref) => controllerOverride, @@ -374,6 +428,7 @@ void main() { final notifier2 = TestNotifier(21); final container = createContainer( overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StateNotifierProvider((_) { return notifier; @@ -396,6 +451,7 @@ void main() { verifyOnly(listener, listener(42, 43)); container.updateOverrides([ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StateNotifierProvider((_) { return notifier2; diff --git a/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart b/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart index 499658000..bea620cdb 100644 --- a/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart +++ b/packages/riverpod/test/providers/state_provider/state_provider_auto_dispose_test.dart @@ -178,6 +178,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StateProvider.autoDispose((ref) => 42, name: 'meh'), ), diff --git a/packages/riverpod/test/providers/state_provider/state_provider_test.dart b/packages/riverpod/test/providers/state_provider/state_provider_test.dart index d7319672f..a82b4e225 100644 --- a/packages/riverpod/test/providers/state_provider/state_provider_test.dart +++ b/packages/riverpod/test/providers/state_provider/state_provider_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_types_on_closure_parameters + import 'package:mockito/mockito.dart'; import 'package:riverpod/riverpod.dart'; import 'package:test/test.dart'; @@ -5,6 +7,44 @@ import 'package:test/test.dart'; import '../../utils.dart'; void main() { + test('supports overrideWith', () { + final provider = StateProvider( + (ref) => 0, + ); + final autoDispose = StateProvider.autoDispose( + (ref) => 0, + ); + final container = createContainer( + overrides: [ + provider.overrideWith((StateProviderRef ref) => 42), + autoDispose.overrideWith((AutoDisposeStateProviderRef ref) => 84), + ], + ); + + expect(container.read(provider), 42); + expect(container.read(autoDispose), 84); + }); + + test('supports family overrideWith', () { + final family = StateProvider.family((ref, arg) => '0 $arg'); + final autoDisposeFamily = StateProvider.autoDispose.family( + (ref, arg) => '0 $arg', + ); + final container = createContainer( + overrides: [ + family.overrideWith( + (StateProviderRef ref, int arg) => '42 $arg', + ), + autoDisposeFamily.overrideWith( + (AutoDisposeStateProviderRef ref, int arg) => '84 $arg', + ), + ], + ); + + expect(container.read(family(10)), '42 10'); + expect(container.read(autoDisposeFamily(10)), '84 10'); + }); + test( 'on refresh, does not notify listeners if the new value is identical to the previous one', () { @@ -250,6 +290,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StateProvider((ref) => 42), ), diff --git a/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart b/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart index d8fdb1df3..8919c76c9 100644 --- a/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart +++ b/packages/riverpod/test/providers/stream_provider/auto_dispose_stream_provider_test.dart @@ -253,6 +253,7 @@ void main() { final container = createContainer( parent: root, overrides: [ + // ignore: deprecated_member_use_from_same_package provider.overrideWithProvider( StreamProvider.autoDispose((ref) => Stream.value(42)), ), diff --git a/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart b/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart index 0f5aa4d22..4acbd6709 100644 --- a/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart +++ b/packages/riverpod/test/providers/stream_provider/stream_provider_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_types_on_closure_parameters + import 'dart:async'; import 'package:mockito/mockito.dart'; @@ -21,6 +23,68 @@ void main() { controller.close(); }); + test('supports overrideWith', () { + final provider = StreamProvider( + (ref) { + ref.state = const AsyncData(0); + return Stream.value(1); + }, + ); + final autoDispose = StreamProvider.autoDispose( + (ref) { + ref.state = const AsyncData(0); + return Stream.value(1); + }, + ); + final container = createContainer( + overrides: [ + provider.overrideWith((StreamProviderRef ref) { + ref.state = const AsyncData(42); + return Stream.value(43); + }), + autoDispose.overrideWith((AutoDisposeStreamProviderRef ref) { + ref.state = const AsyncData(84); + return Stream.value(85); + }), + ], + ); + + expect(container.read(provider).value, 42); + expect(container.read(autoDispose).value, 84); + }); + + test('supports family overrideWith', () { + final family = StreamProvider.family((ref, arg) { + ref.state = AsyncData('0 $arg'); + return Stream.value('1 $arg'); + }); + final autoDisposeFamily = StreamProvider.autoDispose.family( + (ref, arg) { + ref.state = AsyncData('0 $arg'); + return Stream.value('1 $arg'); + }, + ); + final container = createContainer( + overrides: [ + family.overrideWith( + (StreamProviderRef ref, int arg) { + ref.state = AsyncData('42 $arg'); + return Stream.value('43 $arg'); + }, + ), + autoDisposeFamily.overrideWith( + (AutoDisposeStreamProviderRef ref, int arg) { + ref.state = AsyncData('84 $arg'); + return Stream.value('85 $arg'); + }, + ), + ], + ); + + expect(container.read(family(10)).value, '42 10'); + expect(container.read(autoDisposeFamily(10)).value, '84 10'); + }); + test('Emits AsyncLoading before the create function is executed', () async { final container = createContainer(); late AsyncValue state; @@ -286,6 +350,7 @@ void main() { parent: root, overrides: [ provider + // ignore: deprecated_member_use_from_same_package .overrideWithProvider(StreamProvider((ref) => Stream.value(42))), ], ); @@ -621,7 +686,7 @@ void main() { // No value were emitted, so the future will fail. Catching the error to // avoid false positive. - // ignore: unawaited_futures, avoid_types_on_closure_parameters + // ignore: unawaited_futures container.read(provider.future).catchError((Object _) => 0); });