diff --git a/packages/bloc/CHANGELOG.md b/packages/bloc/CHANGELOG.md index 4ccac0d4608..5253ac4dae7 100644 --- a/packages/bloc/CHANGELOG.md +++ b/packages/bloc/CHANGELOG.md @@ -1,3 +1,11 @@ +# 8.0.0-dev.1 + +- **BREAKING**: refactor: remove deprecated `TransitionFunction` +- **BREAKING**: refactor: remove deprecated `transformEvents` +- **BREAKING**: refactor: remove deprecated `mapEventToState` +- **BREAKING**: refactor: remove deprecated `transformTransitions` +- feat: throw `StateError` if an event is added without a registered event handler + # 7.2.1 - fix: `on` should have an `EventTransformer` instead of `EventTransformer` @@ -24,7 +32,7 @@ # 7.2.0-dev.3 -- **BREAKING**: refactor!: require `emit.forEach` `onData` to be synchronous +- **BREAKING**: refactor: require `emit.forEach` `onData` to be synchronous - refactor: minor internal optimizations in `on` implementation # 7.2.0-dev.2 diff --git a/packages/bloc/lib/src/bloc.dart b/packages/bloc/lib/src/bloc.dart index 12b03fa38e9..50431ede1ee 100644 --- a/packages/bloc/lib/src/bloc.dart +++ b/packages/bloc/lib/src/bloc.dart @@ -207,18 +207,6 @@ Please make sure to await all asynchronous operations within event handlers. Future get future => _completer.future; } -/// **@Deprecated - Use `on` with an `EventTransformer` instead. -/// Will be removed in v8.0.0** -/// -/// Signature for a mapper function which takes an [Event] as input -/// and outputs a [Stream] of [Transition] objects. -@Deprecated( - 'Use `on` with an `EventTransformer` instead. ' - 'Will be removed in v8.0.0', -) -typedef TransitionFunction = Stream> - Function(Event); - /// {@template bloc_unhandled_error_exception} /// Exception thrown when an unhandled error occurs within a bloc. /// @@ -249,15 +237,19 @@ class BlocUnhandledErrorException implements Exception { } } +class _Handler { + const _Handler({required this.isType, required this.type}); + final bool Function(dynamic) isType; + final Type type; +} + /// {@template bloc} /// Takes a `Stream` of `Events` as input /// and transforms them into a `Stream` of `States` as output. /// {@endtemplate} abstract class Bloc extends BlocBase { /// {@macro bloc} - Bloc(State initialState) : super(initialState) { - _bindEventsToStates(); - } + Bloc(State initialState) : super(initialState); /// The current [BlocObserver] instance. static BlocObserver observer = BlocObserver(); @@ -279,18 +271,30 @@ abstract class Bloc extends BlocBase { .transform(const _FlatMapStreamTransformer()); }; - StreamSubscription>? _transitionSubscription; - final _eventController = StreamController.broadcast(); final _subscriptions = >[]; - final _handlerTypes = []; + final _handlers = <_Handler>[]; final _emitters = <_Emitter>[]; /// Notifies the [Bloc] of a new [event] which triggers /// all corresponding [EventHandler] instances. /// If [close] has already been called, any subsequent calls to [add] will /// be ignored and will not result in any subsequent state changes. + /// + /// * A [StateError] will be thrown if there is no event handler + /// registered for the incoming [event]. void add(Event event) { + assert(() { + final handlerExists = _handlers.any((handler) => handler.isType(event)); + if (!handlerExists) { + final eventType = event.runtimeType; + throw StateError( + '''add($eventType) was called without a registered event handler.\n''' + '''Make sure to register a handler via on<$eventType>((event, emit) {...})''', + ); + } + return true; + }()); if (_eventController.isClosed) return; try { onEvent(event); @@ -325,52 +329,6 @@ abstract class Bloc extends BlocBase { observer.onEvent(this, event); } - /// **@Deprecated - Use `on` with an `EventTransformer` instead. - /// Will be removed in v8.0.0** - /// - /// Transforms the [events] stream along with a [transitionFn] function into - /// a `Stream`. - /// Events that should be processed by [mapEventToState] need to be passed to - /// [transitionFn]. - /// By default `asyncExpand` is used to ensure all [events] are processed in - /// the order in which they are received. - /// You can override [transformEvents] for advanced usage in order to - /// manipulate the frequency and specificity with which [mapEventToState] is - /// called as well as which [events] are processed. - /// - /// For example, if you only want [mapEventToState] to be called on the most - /// recent [Event] you can use `switchMap` instead of `asyncExpand`. - /// - /// ```dart - /// @override - /// Stream> transformEvents(events, transitionFn) { - /// return events.switchMap(transitionFn); - /// } - /// ``` - /// - /// Alternatively, if you only want [mapEventToState] to be called for - /// distinct [events]: - /// - /// ```dart - /// @override - /// Stream> transformEvents(events, transitionFn) { - /// return super.transformEvents( - /// events.distinct(), - /// transitionFn, - /// ); - /// } - /// ``` - @Deprecated( - 'Use `on` with an `EventTransformer` instead. ' - 'Will be removed in v8.0.0', - ) - Stream> transformEvents( - Stream events, - TransitionFunction transitionFn, - ) { - return events.asyncExpand(transitionFn); - } - /// {@template emit} /// **[emit] should never be used outside of tests.** /// @@ -412,14 +370,14 @@ abstract class Bloc extends BlocBase { EventTransformer? transformer, }) { assert(() { - final handlerExists = _handlerTypes.any((type) => type == E); + final handlerExists = _handlers.any((handler) => handler.type == E); if (handlerExists) { throw StateError( 'on<$E> was called multiple times. ' 'There should only be a single event handler per event type.', ); } - _handlerTypes.add(E); + _handlers.add(_Handler(isType: (dynamic e) => e is E, type: E)); return true; }()); @@ -468,15 +426,6 @@ abstract class Bloc extends BlocBase { _subscriptions.add(subscription); } - /// **@Deprecated - Use on instead. Will be removed in v8.0.0** - /// - /// Must be implemented when a class extends [Bloc]. - /// [mapEventToState] is called whenever an [event] is [add]ed - /// and is responsible for converting that [event] into a new [state]. - /// [mapEventToState] can `yield` zero, one, or multiple states for an event. - @Deprecated('Use on instead. Will be removed in v8.0.0') - Stream mapEventToState(Event event) async* {} - /// Called whenever a [transition] occurs with the given [transition]. /// A [transition] occurs when a new `event` is added /// and a new state is `emitted` from a corresponding [EventHandler]. @@ -506,35 +455,6 @@ abstract class Bloc extends BlocBase { Bloc.observer.onTransition(this, transition); } - /// **@Deprecated - Override `Stream get stream` instead. - /// Will be removed in v8.0.0** - /// - /// Transforms the `Stream` into a new `Stream`. - /// By default [transformTransitions] returns - /// the incoming `Stream`. - /// You can override [transformTransitions] for advanced usage in order to - /// manipulate the frequency and specificity at which `transitions` - /// (state changes) occur. - /// - /// For example, if you want to debounce outgoing state changes: - /// - /// ```dart - /// @override - /// Stream> transformTransitions( - /// Stream> transitions, - /// ) { - /// return transitions.debounceTime(Duration(seconds: 1)); - /// } - /// ``` - @Deprecated( - 'Override `Stream get stream` instead. Will be removed in v8.0.0', - ) - Stream> transformTransitions( - Stream> transitions, - ) { - return transitions; - } - /// Closes the `event` and `state` `Streams`. /// This method should be called when a [Bloc] is no longer needed. /// Once [close] is called, `events` that are [add]ed will not be @@ -548,48 +468,8 @@ abstract class Bloc extends BlocBase { for (final emitter in _emitters) emitter.cancel(); await Future.wait(_emitters.map((e) => e.future)); await Future.wait(_subscriptions.map((s) => s.cancel())); - await _transitionSubscription?.cancel(); return super.close(); } - - void _bindEventsToStates() { - void assertNoMixedUsage() { - assert(() { - if (_handlerTypes.isNotEmpty) { - throw StateError( - 'mapEventToState cannot be overridden in ' - 'conjunction with on.', - ); - } - return true; - }()); - } - - _transitionSubscription = transformTransitions( - transformEvents( - _eventController.stream, - (event) => mapEventToState(event).map( - (nextState) => Transition( - currentState: state, - event: event, - nextState: nextState, - ), - ), - ), - ).listen( - (transition) { - if (transition.nextState == state && _emitted) return; - try { - assertNoMixedUsage(); - onTransition(transition); - emit(transition.nextState); - } catch (error, stackTrace) { - onError(error, stackTrace); - } - }, - onError: onError, - ); - } } /// {@template cubit} diff --git a/packages/bloc/pubspec.yaml b/packages/bloc/pubspec.yaml index 575ef4b36f8..87e1e26f451 100644 --- a/packages/bloc/pubspec.yaml +++ b/packages/bloc/pubspec.yaml @@ -1,6 +1,6 @@ name: bloc description: A predictable state management library that helps implement the BLoC (Business Logic Component) design pattern. -version: 7.2.1 +version: 8.0.0-dev.1 repository: https://github.com/felangel/bloc/tree/master/packages/bloc issue_tracker: https://github.com/felangel/bloc/issues homepage: https://github.com/felangel/bloc diff --git a/packages/bloc/test/bloc_on_test.dart b/packages/bloc/test/bloc_on_test.dart index 6652b5044e5..671d0996d2e 100644 --- a/packages/bloc/test/bloc_on_test.dart +++ b/packages/bloc/test/bloc_on_test.dart @@ -53,7 +53,7 @@ class MissingHandlerBloc extends Bloc { } void main() { - group('on', () { + group('on', () { test('throws StateError when handler is registered more than once', () { const expectedMessage = 'on was called multiple times. ' 'There should only be a single event handler per event type.'; @@ -62,6 +62,16 @@ void main() { expect(() => DuplicateHandlerBloc(), expected); }); + test('throws StateError when handler is missing', () { + const expectedMessage = + '''add(TestEventA) was called without a registered event handler.\n''' + '''Make sure to register a handler via on((event, emit) {...})'''; + final expected = throwsA( + isA().having((e) => e.message, 'message', expectedMessage), + ); + expect(() => MissingHandlerBloc()..add(TestEventA()), expected); + }); + test('invokes all on when event E is added where E is T', () async { var onEventCallCount = 0; var onACallCount = 0; diff --git a/packages/bloc/test/legacy/bloc_observer_test.dart b/packages/bloc/test/legacy/bloc_observer_test.dart deleted file mode 100644 index 7e45f6c2028..00000000000 --- a/packages/bloc/test/legacy/bloc_observer_test.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'package:bloc/bloc.dart'; -import 'package:test/test.dart'; - -import 'blocs/blocs.dart'; - -void main() { - final bloc = CounterBloc(); - const event = CounterEvent.increment; - const change = Change(currentState: 0, nextState: 1); - const transition = Transition( - currentState: 0, - event: CounterEvent.increment, - nextState: 1, - ); - group('BlocObserver', () { - group('onCreate', () { - test('does nothing by default', () { - // ignore: invalid_use_of_protected_member - BlocObserver().onCreate(bloc); - }); - }); - - group('onEvent', () { - test('does nothing by default', () { - // ignore: invalid_use_of_protected_member - BlocObserver().onEvent(bloc, event); - }); - }); - - group('onChange', () { - test('does nothing by default', () { - // ignore: invalid_use_of_protected_member - BlocObserver().onChange(bloc, change); - }); - }); - - group('onTransition', () { - test('does nothing by default', () { - // ignore: invalid_use_of_protected_member - BlocObserver().onTransition(bloc, transition); - }); - }); - - group('onError', () { - test('does nothing by default', () { - // ignore: invalid_use_of_protected_member - BlocObserver().onError(bloc, event, StackTrace.current); - }); - }); - - group('onClose', () { - test('does nothing by default', () { - // ignore: invalid_use_of_protected_member - BlocObserver().onClose(bloc); - }); - }); - }); -} diff --git a/packages/bloc/test/legacy/bloc_test.dart b/packages/bloc/test/legacy/bloc_test.dart deleted file mode 100644 index 1e27c0cbd33..00000000000 --- a/packages/bloc/test/legacy/bloc_test.dart +++ /dev/null @@ -1,993 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:test/test.dart'; - -import 'blocs/blocs.dart'; - -class MockBlocObserver extends Mock implements BlocObserver {} - -class FakeBlocBase extends Fake implements BlocBase {} - -void main() { - group('Bloc Tests', () { - group('Simple Bloc', () { - late SimpleBloc simpleBloc; - late MockBlocObserver observer; - - setUp(() { - simpleBloc = SimpleBloc(); - observer = MockBlocObserver(); - Bloc.observer = observer; - }); - - test('triggers onCreate on observer when instantiated', () { - final bloc = SimpleBloc(); - // ignore: invalid_use_of_protected_member - verify(() => observer.onCreate(bloc)).called(1); - }); - - test('triggers onClose on observer when closed', () async { - final bloc = SimpleBloc(); - await bloc.close(); - // ignore: invalid_use_of_protected_member - verify(() => observer.onClose(bloc)).called(1); - }); - - test('close does not emit new states over the state stream', () async { - final expectedStates = [emitsDone]; - - unawaited(expectLater(simpleBloc.stream, emitsInOrder(expectedStates))); - - await simpleBloc.close(); - }); - - test('state returns correct value initially', () { - expect(simpleBloc.state, ''); - }); - - test('should map single event to correct state', () { - final expectedStates = ['data', emitsDone]; - - expectLater( - simpleBloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - simpleBloc, - const Transition( - currentState: '', - event: 'event', - nextState: 'data', - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - simpleBloc, - const Change(currentState: '', nextState: 'data'), - ), - ).called(1); - expect(simpleBloc.state, 'data'); - }); - - simpleBloc - ..add('event') - ..close(); - }); - - test('should map multiple events to correct states', () { - final expectedStates = ['data', emitsDone]; - - expectLater( - simpleBloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - simpleBloc, - const Transition( - currentState: '', - event: 'event1', - nextState: 'data', - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - simpleBloc, - const Change(currentState: '', nextState: 'data'), - ), - ).called(1); - expect(simpleBloc.state, 'data'); - }); - - simpleBloc - ..add('event1') - ..add('event2') - ..add('event3') - ..close(); - }); - - test('is a broadcast stream', () { - final expectedStates = ['data', emitsDone]; - - expect(simpleBloc.stream.isBroadcast, isTrue); - expectLater(simpleBloc.stream, emitsInOrder(expectedStates)); - expectLater(simpleBloc.stream, emitsInOrder(expectedStates)); - - simpleBloc - ..add('event') - ..close(); - }); - - test('multiple subscribers receive the latest state', () { - final expectedStates = const ['data']; - - expectLater(simpleBloc.stream, emitsInOrder(expectedStates)); - expectLater(simpleBloc.stream, emitsInOrder(expectedStates)); - expectLater(simpleBloc.stream, emitsInOrder(expectedStates)); - - simpleBloc.add('event'); - }); - }); - - group('Complex Bloc', () { - late ComplexBloc complexBloc; - late MockBlocObserver observer; - - setUp(() { - complexBloc = ComplexBloc(); - observer = MockBlocObserver(); - Bloc.observer = observer; - }); - - test('close does not emit new states over the state stream', () async { - final expectedStates = [emitsDone]; - - unawaited( - expectLater(complexBloc.stream, emitsInOrder(expectedStates)), - ); - - await complexBloc.close(); - }); - - test('state returns correct value initially', () { - expect(complexBloc.state, ComplexStateA()); - }); - - test('should map single event to correct state', () { - final expectedStates = [ComplexStateB()]; - - expectLater( - complexBloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - complexBloc, - Transition( - currentState: ComplexStateA(), - event: ComplexEventB(), - nextState: ComplexStateB(), - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - complexBloc, - Change( - currentState: ComplexStateA(), - nextState: ComplexStateB(), - ), - ), - ).called(1); - expect(complexBloc.state, ComplexStateB()); - }); - - complexBloc.add(ComplexEventB()); - }); - - test('should map multiple events to correct states', () async { - final expectedStates = [ - ComplexStateB(), - ComplexStateD(), - ComplexStateA(), - ComplexStateC(), - ]; - - unawaited( - expectLater(complexBloc.stream, emitsInOrder(expectedStates)), - ); - - complexBloc.add(ComplexEventA()); - await Future.delayed(const Duration(milliseconds: 20)); - complexBloc.add(ComplexEventB()); - await Future.delayed(const Duration(milliseconds: 20)); - complexBloc.add(ComplexEventC()); - await Future.delayed(const Duration(milliseconds: 20)); - complexBloc.add(ComplexEventD()); - await Future.delayed(const Duration(milliseconds: 200)); - complexBloc - ..add(ComplexEventC()) - ..add(ComplexEventA()); - await Future.delayed(const Duration(milliseconds: 120)); - complexBloc.add(ComplexEventC()); - }); - - test('is a broadcast stream', () { - final expectedStates = [ComplexStateB()]; - - expect(complexBloc.stream.isBroadcast, isTrue); - expectLater(complexBloc.stream, emitsInOrder(expectedStates)); - expectLater(complexBloc.stream, emitsInOrder(expectedStates)); - - complexBloc.add(ComplexEventB()); - }); - - test('multiple subscribers receive the latest state', () { - final expected = [ComplexStateB()]; - - expectLater(complexBloc.stream, emitsInOrder(expected)); - expectLater(complexBloc.stream, emitsInOrder(expected)); - expectLater(complexBloc.stream, emitsInOrder(expected)); - - complexBloc.add(ComplexEventB()); - }); - }); - - group('CounterBloc', () { - late CounterBloc counterBloc; - late MockBlocObserver observer; - late List transitions; - late List events; - - setUp(() { - events = []; - transitions = []; - counterBloc = CounterBloc( - onEventCallback: events.add, - onTransitionCallback: (transition) { - transitions.add(transition.toString()); - }, - ); - observer = MockBlocObserver(); - Bloc.observer = observer; - }); - - test('state returns correct value initially', () { - expect(counterBloc.state, 0); - expect(events.isEmpty, true); - expect(transitions.isEmpty, true); - }); - - test('single Increment event updates state to 1', () { - final expectedStates = [1, emitsDone]; - final expectedTransitions = [ - '''Transition { currentState: 0, event: CounterEvent.increment, nextState: 1 }''' - ]; - - expectLater( - counterBloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - expectLater(transitions, expectedTransitions); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - counterBloc, - const Transition( - currentState: 0, - event: CounterEvent.increment, - nextState: 1, - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - counterBloc, - const Change(currentState: 0, nextState: 1), - ), - ).called(1); - expect(counterBloc.state, 1); - }); - - counterBloc - ..add(CounterEvent.increment) - ..close(); - }); - - test('multiple Increment event updates state to 3', () { - final expectedStates = [1, 2, 3, emitsDone]; - final expectedTransitions = [ - '''Transition { currentState: 0, event: CounterEvent.increment, nextState: 1 }''', - '''Transition { currentState: 1, event: CounterEvent.increment, nextState: 2 }''', - '''Transition { currentState: 2, event: CounterEvent.increment, nextState: 3 }''', - ]; - - expectLater( - counterBloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - expect(transitions, expectedTransitions); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - counterBloc, - const Transition( - currentState: 0, - event: CounterEvent.increment, - nextState: 1, - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - counterBloc, - const Change(currentState: 0, nextState: 1), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - counterBloc, - const Transition( - currentState: 1, - event: CounterEvent.increment, - nextState: 2, - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - counterBloc, - const Change(currentState: 1, nextState: 2), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - counterBloc, - const Transition( - currentState: 2, - event: CounterEvent.increment, - nextState: 3, - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - counterBloc, - const Change(currentState: 2, nextState: 3), - ), - ).called(1); - }); - - counterBloc - ..add(CounterEvent.increment) - ..add(CounterEvent.increment) - ..add(CounterEvent.increment) - ..close(); - }); - - test('is a broadcast stream', () { - final expectedStates = [1, emitsDone]; - - expect(counterBloc.stream.isBroadcast, isTrue); - expectLater(counterBloc.stream, emitsInOrder(expectedStates)); - expectLater(counterBloc.stream, emitsInOrder(expectedStates)); - - counterBloc - ..add(CounterEvent.increment) - ..close(); - }); - - test('multiple subscribers receive the latest state', () { - const expected = [1]; - - expectLater(counterBloc.stream, emitsInOrder(expected)); - expectLater(counterBloc.stream, emitsInOrder(expected)); - expectLater(counterBloc.stream, emitsInOrder(expected)); - - counterBloc.add(CounterEvent.increment); - }); - }); - - group('Async Bloc', () { - late AsyncBloc asyncBloc; - late MockBlocObserver observer; - - setUpAll(() { - registerFallbackValue>(FakeBlocBase()); - registerFallbackValue(StackTrace.empty); - }); - - setUp(() { - asyncBloc = AsyncBloc(); - observer = MockBlocObserver(); - Bloc.observer = observer; - }); - - test('close does not emit new states over the state stream', () async { - final expectedStates = [emitsDone]; - - unawaited(expectLater(asyncBloc.stream, emitsInOrder(expectedStates))); - - await asyncBloc.close(); - }); - - test( - 'close while events are pending finishes processing pending events ' - 'and does not trigger onError', () async { - final expectedStates = [ - AsyncState.initial().copyWith(isLoading: true), - AsyncState.initial().copyWith(isSuccess: true), - ]; - final states = []; - - asyncBloc - // ignore: deprecated_member_use_from_same_package - ..listen(states.add) - ..add(AsyncEvent()); - - await asyncBloc.close(); - - expect(states, expectedStates); - // ignore: invalid_use_of_protected_member - verifyNever(() => observer.onError(any(), any(), any())); - }); - - test('state returns correct value initially', () { - expect(asyncBloc.state, AsyncState.initial()); - }); - - test('should map single event to correct state', () { - final expectedStates = [ - AsyncState(isLoading: true, hasError: false, isSuccess: false), - AsyncState(isLoading: false, hasError: false, isSuccess: true), - emitsDone, - ]; - - expectLater( - asyncBloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - asyncBloc, - Transition( - currentState: AsyncState( - isLoading: false, - hasError: false, - isSuccess: false, - ), - event: AsyncEvent(), - nextState: AsyncState( - isLoading: true, - hasError: false, - isSuccess: false, - ), - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - asyncBloc, - Change( - currentState: AsyncState( - isLoading: false, - hasError: false, - isSuccess: false, - ), - nextState: AsyncState( - isLoading: true, - hasError: false, - isSuccess: false, - ), - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onTransition( - asyncBloc, - Transition( - currentState: AsyncState( - isLoading: true, - hasError: false, - isSuccess: false, - ), - event: AsyncEvent(), - nextState: AsyncState( - isLoading: false, - hasError: false, - isSuccess: true, - ), - ), - ), - ).called(1); - verify( - // ignore: invalid_use_of_protected_member - () => observer.onChange( - asyncBloc, - Change( - currentState: AsyncState( - isLoading: true, - hasError: false, - isSuccess: false, - ), - nextState: AsyncState( - isLoading: false, - hasError: false, - isSuccess: true, - ), - ), - ), - ).called(1); - expect( - asyncBloc.state, - AsyncState( - isLoading: false, - hasError: false, - isSuccess: true, - ), - ); - }); - - asyncBloc - ..add(AsyncEvent()) - ..close(); - }); - - test('is a broadcast stream', () { - final expectedStates = [ - AsyncState(isLoading: true, hasError: false, isSuccess: false), - AsyncState(isLoading: false, hasError: false, isSuccess: true), - emitsDone, - ]; - - expect(asyncBloc.stream.isBroadcast, isTrue); - expectLater(asyncBloc.stream, emitsInOrder(expectedStates)); - expectLater(asyncBloc.stream, emitsInOrder(expectedStates)); - - asyncBloc - ..add(AsyncEvent()) - ..close(); - }); - - test('multiple subscribers receive the latest state', () { - final expected = [ - AsyncState(isLoading: true, hasError: false, isSuccess: false), - AsyncState(isLoading: false, hasError: false, isSuccess: true), - ]; - - expectLater(asyncBloc.stream, emitsInOrder(expected)); - expectLater(asyncBloc.stream, emitsInOrder(expected)); - expectLater(asyncBloc.stream, emitsInOrder(expected)); - - asyncBloc.add(AsyncEvent()); - }); - }); - - group('flatMap', () { - test('maintains correct transition composition', () { - final expectedTransitions = >[ - const Transition( - currentState: 0, - event: CounterEvent.decrement, - nextState: -1, - ), - const Transition( - currentState: -1, - event: CounterEvent.increment, - nextState: 0, - ), - ]; - - final expectedStates = [-1, 0, emitsDone]; - final transitions = >[]; - final flatMapBloc = FlatMapBloc( - onTransitionCallback: transitions.add, - ); - - expectLater( - flatMapBloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - expect(transitions, expectedTransitions); - }); - flatMapBloc - ..add(CounterEvent.decrement) - ..add(CounterEvent.increment) - ..close(); - }); - }); - - group('mergeBloc', () { - test('maintains correct transition composition', () { - final expectedTransitions = >[ - const Transition( - currentState: 0, - event: CounterEvent.increment, - nextState: 1, - ), - const Transition( - currentState: 1, - event: CounterEvent.decrement, - nextState: 0, - ), - const Transition( - currentState: 0, - event: CounterEvent.decrement, - nextState: -1, - ), - ]; - final expectedStates = [1, 0, -1, emitsDone]; - final transitions = >[]; - - final bloc = MergeBloc( - onTransitionCallback: transitions.add, - ); - - expectLater( - bloc.stream, - emitsInOrder(expectedStates), - ).then((dynamic _) { - expect(transitions, expectedTransitions); - }); - bloc - ..add(CounterEvent.increment) - ..add(CounterEvent.increment) - ..add(CounterEvent.decrement) - ..add(CounterEvent.decrement) - ..close(); - }); - }); - - group('SeededBloc', () { - test('does not emit repeated states', () { - final seededBloc = SeededBloc(seed: 0, states: [1, 2, 1, 1]); - final expectedStates = [1, 2, 1, emitsDone]; - - expectLater(seededBloc.stream, emitsInOrder(expectedStates)); - - seededBloc - ..add('event') - ..close(); - }); - - test('can emit initial state only once', () { - final seededBloc = SeededBloc(seed: 0, states: [0, 0]); - final expectedStates = [0, emitsDone]; - - expectLater(seededBloc.stream, emitsInOrder(expectedStates)); - - seededBloc - ..add('event') - ..close(); - }); - - test( - 'can emit initial state and ' - 'continue emitting distinct states', () { - final seededBloc = SeededBloc(seed: 0, states: [0, 0, 1]); - final expectedStates = [0, 1, emitsDone]; - - expectLater(seededBloc.stream, emitsInOrder(expectedStates)); - - seededBloc - ..add('event') - ..close(); - }); - - test('discards subsequent duplicate states (distinct events)', () { - final seededBloc = SeededBloc(seed: 0, states: [1, 1]); - final expectedStates = [1, emitsDone]; - - expectLater(seededBloc.stream, emitsInOrder(expectedStates)); - - seededBloc - ..add('eventA') - ..add('eventB') - ..add('eventC') - ..close(); - }); - - test('discards subsequent duplicate states (same event)', () { - final seededBloc = SeededBloc(seed: 0, states: [1, 1]); - final expectedStates = [1, emitsDone]; - - expectLater(seededBloc.stream, emitsInOrder(expectedStates)); - - seededBloc - ..add('event') - ..add('event') - ..add('event') - ..close(); - }); - }); - - group('MixedCounterBloc', () { - test( - 'throws StateError when on and mapEventToState ' - 'are used in conjunction', () { - runZonedGuarded( - () => MixedCounterBloc()..add(CounterEvent.increment), - (Object error, StackTrace stackTrace) { - expect( - (error as BlocUnhandledErrorException).toString(), - contains( - 'mapEventToState cannot be overridden in ' - 'conjunction with on.', - ), - ); - }, - ); - }); - }); - - group('Exception', () { - test('does not break stream', () { - runZonedGuarded(() { - final expectedStates = [-1, emitsDone]; - final counterBloc = CounterExceptionBloc(); - - expectLater(counterBloc.stream, emitsInOrder(expectedStates)); - - counterBloc - ..add(CounterEvent.increment) - ..add(CounterEvent.decrement) - ..close(); - }, (Object error, StackTrace stackTrace) { - expect( - (error as BlocUnhandledErrorException).toString(), - contains( - 'Unhandled error Exception: fatal exception occurred ' - 'in Instance of \'CounterExceptionBloc\'.', - ), - ); - expect(stackTrace, isNotNull); - expect(stackTrace, isNot(StackTrace.empty)); - }); - }); - - test('addError triggers onError', () async { - final expectedError = Exception('fatal exception'); - - runZonedGuarded(() { - OnExceptionBloc( - exception: expectedError, - onErrorCallback: (Object _, StackTrace __) {}, - )..addError(expectedError, StackTrace.current); - }, (Object error, StackTrace stackTrace) { - expect( - (error as BlocUnhandledErrorException).toString(), - contains( - 'Unhandled error Exception: fatal exception occurred ' - 'in Instance of \'OnExceptionBloc\'.', - ), - ); - expect(stackTrace, isNotNull); - expect(stackTrace, isNot(StackTrace.empty)); - }); - }); - - test('triggers onError from mapEventToState', () { - runZonedGuarded(() { - final exception = Exception('fatal exception'); - Object? expectedError; - StackTrace? expectedStacktrace; - - final onExceptionBloc = OnExceptionBloc( - exception: exception, - onErrorCallback: (Object error, StackTrace stackTrace) { - expectedError = error; - expectedStacktrace = stackTrace; - }); - - expectLater( - onExceptionBloc.stream, - emitsInOrder([emitsDone]), - ).then((dynamic _) { - expect(expectedError, exception); - expect(expectedStacktrace, isNotNull); - expect(expectedStacktrace, isNot(StackTrace.empty)); - }); - - onExceptionBloc - ..add(CounterEvent.increment) - ..close(); - }, (Object error, StackTrace stackTrace) { - expect( - (error as BlocUnhandledErrorException).toString(), - contains( - 'Unhandled error Exception: fatal exception occurred ' - 'in Instance of \'OnExceptionBloc\'.', - ), - ); - expect(stackTrace, isNotNull); - expect(stackTrace, isNot(StackTrace.empty)); - }); - }); - - test('triggers onError from onEvent', () { - runZonedGuarded(() { - final exception = Exception('fatal exception'); - - OnEventErrorBloc(exception: exception) - ..add(CounterEvent.increment) - ..close(); - }, (Object error, StackTrace stackTrace) { - expect( - (error as BlocUnhandledErrorException).toString(), - contains( - 'Unhandled error Exception: fatal exception occurred ' - 'in Instance of \'OnEventErrorBloc\'.', - ), - ); - expect(stackTrace, isNotNull); - expect(stackTrace, isNot(StackTrace.empty)); - }); - }); - - test('does not trigger onError from add', () { - runZonedGuarded(() { - Object? capturedError; - StackTrace? capturedStacktrace; - final counterBloc = CounterBloc( - onErrorCallback: (error, stackTrace) { - capturedError = error; - capturedStacktrace = stackTrace; - }, - ); - - expectLater( - counterBloc.stream, - emitsInOrder([emitsDone]), - ).then((dynamic _) { - expect(capturedError, isNull); - expect(capturedStacktrace, isNull); - }); - - counterBloc - ..close() - ..add(CounterEvent.increment); - }, (Object _, StackTrace __) { - fail('should not throw when add is called after bloc is closed'); - }); - }); - }); - - group('Error', () { - test('does not break stream', () { - runZonedGuarded( - () { - final expectedStates = [-1, emitsDone]; - final counterBloc = CounterErrorBloc(); - - expectLater(counterBloc.stream, emitsInOrder(expectedStates)); - - counterBloc - ..add(CounterEvent.increment) - ..add(CounterEvent.decrement) - ..close(); - }, - (Object _, StackTrace __) {}, - ); - }); - - test('triggers onError from mapEventToState', () { - runZonedGuarded( - () { - final error = Error(); - Object? expectedError; - StackTrace? expectedStacktrace; - - final onErrorBloc = OnErrorBloc( - error: error, - onErrorCallback: (Object error, StackTrace stackTrace) { - expectedError = error; - expectedStacktrace = stackTrace; - }, - ); - - expectLater( - onErrorBloc.stream, - emitsInOrder([emitsDone]), - ).then((dynamic _) { - expect(expectedError, error); - expect(expectedStacktrace, isNotNull); - }); - - onErrorBloc - ..add(CounterEvent.increment) - ..close(); - }, - (Object _, StackTrace __) {}, - ); - }); - - test('triggers onError from onTransition', () { - runZonedGuarded( - () { - final error = Error(); - Object? expectedError; - StackTrace? expectedStacktrace; - - final onTransitionErrorBloc = OnTransitionErrorBloc( - error: error, - onErrorCallback: (Object error, StackTrace stackTrace) { - expectedError = error; - expectedStacktrace = stackTrace; - }, - ); - - expectLater( - onTransitionErrorBloc.stream, - emitsInOrder([emitsDone]), - ).then((dynamic _) { - expect(expectedError, error); - expect(expectedStacktrace, isNotNull); - expect(onTransitionErrorBloc.state, 0); - }); - - onTransitionErrorBloc - ..add(CounterEvent.increment) - ..close(); - }, - (Object _, StackTrace __) {}, - ); - }); - }); - - group('emit', () { - test('updates the state', () async { - final counterBloc = CounterBloc(); - unawaited( - expectLater(counterBloc.stream, emitsInOrder(const [42])), - ); - counterBloc.emit(42); - expect(counterBloc.state, 42); - await counterBloc.close(); - }); - }); - - group('close', () { - test('emits done (sync)', () { - final bloc = CounterBloc()..close(); - expect(bloc.stream, emitsDone); - }); - - test('emits done (async)', () async { - final bloc = CounterBloc(); - await bloc.close(); - expect(bloc.stream, emitsDone); - }); - }); - - group('isClosed', () { - test('returns true after bloc is closed', () async { - final bloc = CounterBloc(); - expect(bloc.isClosed, isFalse); - await bloc.close(); - expect(bloc.isClosed, isTrue); - }); - }); - }); -} - -void unawaited(Future future) {} diff --git a/packages/bloc/test/legacy/blocs/async/async_bloc.dart b/packages/bloc/test/legacy/blocs/async/async_bloc.dart deleted file mode 100644 index 9a91ab54a52..00000000000 --- a/packages/bloc/test/legacy/blocs/async/async_bloc.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; - -part 'async_event.dart'; -part 'async_state.dart'; - -class AsyncBloc extends Bloc { - AsyncBloc() : super(AsyncState.initial()); - - @override - Stream mapEventToState(AsyncEvent event) async* { - yield state.copyWith(isLoading: true); - await Future.delayed(const Duration(milliseconds: 500)); - yield state.copyWith(isLoading: false, isSuccess: true); - } -} diff --git a/packages/bloc/test/legacy/blocs/async/async_event.dart b/packages/bloc/test/legacy/blocs/async/async_event.dart deleted file mode 100644 index a2e775a23c8..00000000000 --- a/packages/bloc/test/legacy/blocs/async/async_event.dart +++ /dev/null @@ -1,20 +0,0 @@ -part of 'async_bloc.dart'; - -@immutable -class AsyncEvent { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is AsyncEvent && runtimeType == other.runtimeType; - - @override - int get hashCode => runtimeType.hashCode; - - @override - String toString() => 'AsyncEvent'; -} diff --git a/packages/bloc/test/legacy/blocs/async/async_state.dart b/packages/bloc/test/legacy/blocs/async/async_state.dart deleted file mode 100644 index c7cc8cb1a62..00000000000 --- a/packages/bloc/test/legacy/blocs/async/async_state.dart +++ /dev/null @@ -1,48 +0,0 @@ -part of 'async_bloc.dart'; - -@immutable -class AsyncState { - AsyncState({ - required this.isLoading, - required this.hasError, - required this.isSuccess, - }); - - factory AsyncState.initial() { - return AsyncState(isLoading: false, hasError: false, isSuccess: false); - } - - final bool isLoading; - final bool hasError; - final bool isSuccess; - - AsyncState copyWith({bool? isLoading, bool? hasError, bool? isSuccess}) { - return AsyncState( - isLoading: isLoading ?? this.isLoading, - hasError: hasError ?? this.hasError, - isSuccess: isSuccess ?? this.isSuccess); - } - - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is AsyncState && - runtimeType == other.runtimeType && - isLoading == other.isLoading && - hasError == other.hasError && - isSuccess == other.isSuccess; - - @override - int get hashCode => - isLoading.hashCode ^ hasError.hashCode ^ isSuccess.hashCode; - - @override - String toString() => - 'AsyncState { isLoading: $isLoading, hasError: $hasError, ' - 'isSuccess: $isSuccess }'; -} diff --git a/packages/bloc/test/legacy/blocs/blocs.dart b/packages/bloc/test/legacy/blocs/blocs.dart deleted file mode 100644 index b44f7a358ba..00000000000 --- a/packages/bloc/test/legacy/blocs/blocs.dart +++ /dev/null @@ -1,5 +0,0 @@ -export './async/async_bloc.dart'; -export './complex/complex_bloc.dart'; -export './counter/counter.dart'; -export './seeded/seeded_bloc.dart'; -export './simple/simple_bloc.dart'; diff --git a/packages/bloc/test/legacy/blocs/complex/complex_bloc.dart b/packages/bloc/test/legacy/blocs/complex/complex_bloc.dart deleted file mode 100644 index d3c0b1ec479..00000000000 --- a/packages/bloc/test/legacy/blocs/complex/complex_bloc.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; -import 'package:stream_transform/stream_transform.dart'; - -part 'complex_event.dart'; -part 'complex_state.dart'; - -class ComplexBloc extends Bloc { - ComplexBloc() : super(ComplexStateA()); - - @override - Stream> transformEvents( - Stream events, - // ignore: deprecated_member_use_from_same_package - TransitionFunction transitionFn, - ) { - return events.switchMap(transitionFn); - } - - @override - Stream mapEventToState(ComplexEvent event) async* { - if (event is ComplexEventA) { - yield ComplexStateA(); - } else if (event is ComplexEventB) { - yield ComplexStateB(); - } else if (event is ComplexEventC) { - await Future.delayed(const Duration(milliseconds: 100)); - yield ComplexStateC(); - } else if (event is ComplexEventD) { - await Future.delayed(const Duration(milliseconds: 100)); - yield ComplexStateD(); - } - } - - @override - Stream> transformTransitions( - Stream> transitions, - ) { - return transitions.debounce(const Duration(milliseconds: 50)); - } -} diff --git a/packages/bloc/test/legacy/blocs/complex/complex_event.dart b/packages/bloc/test/legacy/blocs/complex/complex_event.dart deleted file mode 100644 index 004fe9f6c1d..00000000000 --- a/packages/bloc/test/legacy/blocs/complex/complex_event.dart +++ /dev/null @@ -1,64 +0,0 @@ -part of 'complex_bloc.dart'; - -@immutable -abstract class ComplexEvent {} - -class ComplexEventA extends ComplexEvent { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexEventA && runtimeType == other.runtimeType; - - @override - int get hashCode => 0; -} - -class ComplexEventB extends ComplexEvent { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexEventB && runtimeType == other.runtimeType; - - @override - int get hashCode => 1; -} - -class ComplexEventC extends ComplexEvent { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexEventC && runtimeType == other.runtimeType; - - @override - int get hashCode => 2; -} - -class ComplexEventD extends ComplexEvent { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexEventD && runtimeType == other.runtimeType; - - @override - int get hashCode => 3; -} diff --git a/packages/bloc/test/legacy/blocs/complex/complex_state.dart b/packages/bloc/test/legacy/blocs/complex/complex_state.dart deleted file mode 100644 index a9f198e4817..00000000000 --- a/packages/bloc/test/legacy/blocs/complex/complex_state.dart +++ /dev/null @@ -1,64 +0,0 @@ -part of 'complex_bloc.dart'; - -@immutable -abstract class ComplexState {} - -class ComplexStateA extends ComplexState { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexStateA && runtimeType == other.runtimeType; - - @override - int get hashCode => 0; -} - -class ComplexStateB extends ComplexState { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexStateB && runtimeType == other.runtimeType; - - @override - int get hashCode => 1; -} - -class ComplexStateC extends ComplexState { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexStateC && runtimeType == other.runtimeType; - - @override - int get hashCode => 2; -} - -class ComplexStateD extends ComplexState { - @override - bool operator ==( - Object other, - ) => - identical( - this, - other, - ) || - other is ComplexStateD && runtimeType == other.runtimeType; - - @override - int get hashCode => 3; -} diff --git a/packages/bloc/test/legacy/blocs/counter/counter.dart b/packages/bloc/test/legacy/blocs/counter/counter.dart deleted file mode 100644 index 96c838b0896..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/counter.dart +++ /dev/null @@ -1,10 +0,0 @@ -export './counter_bloc.dart'; -export './counter_error_bloc.dart'; -export './counter_exception_bloc.dart'; -export './flat_map_bloc.dart'; -export './merge_bloc.dart'; -export './mixed_counter_bloc.dart'; -export './on_error_bloc.dart'; -export './on_event_error_bloc.dart'; -export './on_exception_bloc.dart'; -export './on_transition_error_bloc.dart'; diff --git a/packages/bloc/test/legacy/blocs/counter/counter_bloc.dart b/packages/bloc/test/legacy/blocs/counter/counter_bloc.dart deleted file mode 100644 index b0955535d5e..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/counter_bloc.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -typedef OnEventCallback = Function(CounterEvent); -typedef OnTransitionCallback = Function(Transition); -typedef OnErrorCallback = Function(Object error, StackTrace? stackTrace); - -enum CounterEvent { increment, decrement } - -class CounterBloc extends Bloc { - CounterBloc({ - this.onEventCallback, - this.onTransitionCallback, - this.onErrorCallback, - }) : super(0); - - final OnEventCallback? onEventCallback; - final OnTransitionCallback? onTransitionCallback; - final OnErrorCallback? onErrorCallback; - - @override - Stream mapEventToState(CounterEvent event) async* { - switch (event) { - case CounterEvent.decrement: - yield state - 1; - break; - case CounterEvent.increment: - yield state + 1; - break; - } - } - - @override - void onEvent(CounterEvent event) { - super.onEvent(event); - onEventCallback?.call(event); - } - - @override - void onTransition(Transition transition) { - super.onTransition(transition); - onTransitionCallback?.call(transition); - } - - @override - void onError(Object error, StackTrace stackTrace) { - onErrorCallback?.call(error, stackTrace); - super.onError(error, stackTrace); - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/counter_error_bloc.dart b/packages/bloc/test/legacy/blocs/counter/counter_error_bloc.dart deleted file mode 100644 index 3d93284ecb3..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/counter_error_bloc.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -import '../counter/counter_bloc.dart'; - -class CounterErrorBloc extends Bloc { - CounterErrorBloc() : super(0); - - @override - Stream mapEventToState(CounterEvent event) async* { - switch (event) { - case CounterEvent.decrement: - yield state - 1; - break; - case CounterEvent.increment: - throw Error(); - } - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/counter_exception_bloc.dart b/packages/bloc/test/legacy/blocs/counter/counter_exception_bloc.dart deleted file mode 100644 index 73f053fdd43..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/counter_exception_bloc.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -import '../counter/counter_bloc.dart'; - -class CounterExceptionBloc extends Bloc { - CounterExceptionBloc() : super(0); - - @override - Stream mapEventToState(CounterEvent event) async* { - switch (event) { - case CounterEvent.decrement: - yield state - 1; - break; - case CounterEvent.increment: - throw Exception('fatal exception'); - } - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/flat_map_bloc.dart b/packages/bloc/test/legacy/blocs/counter/flat_map_bloc.dart deleted file mode 100644 index 9293e3a486f..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/flat_map_bloc.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:bloc/bloc.dart'; -import 'package:stream_transform/stream_transform.dart'; - -import '../blocs.dart'; - -class FlatMapBloc extends Bloc { - FlatMapBloc({this.onTransitionCallback}) : super(0); - - final void Function(Transition)? onTransitionCallback; - - @override - void onTransition(Transition transition) { - super.onTransition(transition); - onTransitionCallback?.call(transition); - } - - @override - Stream> transformEvents( - Stream events, - // ignore: deprecated_member_use_from_same_package - TransitionFunction transitionFn, - ) { - return events.concurrentAsyncExpand(transitionFn); - } - - @override - Stream mapEventToState( - CounterEvent event, - ) async* { - switch (event) { - case CounterEvent.decrement: - yield state - 1; - break; - case CounterEvent.increment: - yield state + 1; - break; - } - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/merge_bloc.dart b/packages/bloc/test/legacy/blocs/counter/merge_bloc.dart deleted file mode 100644 index 7f1501b0d16..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/merge_bloc.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:bloc/bloc.dart'; -import 'package:stream_transform/stream_transform.dart'; - -import '../blocs.dart'; - -class MergeBloc extends Bloc { - MergeBloc({this.onTransitionCallback}) : super(0); - - final void Function(Transition)? onTransitionCallback; - - @override - void onTransition(Transition transition) { - super.onTransition(transition); - onTransitionCallback?.call(transition); - } - - @override - Stream> transformEvents( - Stream events, - // ignore: deprecated_member_use_from_same_package - TransitionFunction transitionFn, - ) { - final nonDebounceStream = - events.where((event) => event != CounterEvent.increment); - - final debounceStream = events - .where((event) => event == CounterEvent.increment) - .throttle(const Duration(milliseconds: 100)); - - return nonDebounceStream - .merge(debounceStream) - .concurrentAsyncExpand(transitionFn); - } - - @override - Stream mapEventToState( - CounterEvent event, - ) async* { - switch (event) { - case CounterEvent.decrement: - yield state - 1; - break; - case CounterEvent.increment: - yield state + 1; - break; - } - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/mixed_counter_bloc.dart b/packages/bloc/test/legacy/blocs/counter/mixed_counter_bloc.dart deleted file mode 100644 index 68cb42533e7..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/mixed_counter_bloc.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -import '../counter/counter_bloc.dart'; - -class MixedCounterBloc extends Bloc { - MixedCounterBloc() : super(0) { - on((event, emit) => emit(_mapEventToState(event))); - } - - @override - Stream mapEventToState(CounterEvent event) async* { - yield _mapEventToState(event); - } - - int _mapEventToState(CounterEvent event) { - switch (event) { - case CounterEvent.increment: - return state + 1; - case CounterEvent.decrement: - return state - 1; - } - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/on_error_bloc.dart b/packages/bloc/test/legacy/blocs/counter/on_error_bloc.dart deleted file mode 100644 index 7cf3587d8b8..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/on_error_bloc.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -import '../counter/counter_bloc.dart'; - -class OnErrorBloc extends Bloc { - OnErrorBloc({required this.error, required this.onErrorCallback}) : super(0); - - final Function onErrorCallback; - final Error error; - - @override - void onError(Object error, StackTrace stackTrace) { - onErrorCallback(error, stackTrace); - super.onError(error, stackTrace); - } - - @override - Stream mapEventToState(CounterEvent event) async* { - throw error; - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/on_event_error_bloc.dart b/packages/bloc/test/legacy/blocs/counter/on_event_error_bloc.dart deleted file mode 100644 index 7596eda6ef3..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/on_event_error_bloc.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -import '../counter/counter_bloc.dart'; - -class OnEventErrorBloc extends Bloc { - OnEventErrorBloc({required this.exception}) : super(0); - - final Exception exception; - - @override - // ignore: must_call_super - void onEvent(CounterEvent event) { - throw exception; - } - - @override - Stream mapEventToState(CounterEvent event) async* {} -} diff --git a/packages/bloc/test/legacy/blocs/counter/on_exception_bloc.dart b/packages/bloc/test/legacy/blocs/counter/on_exception_bloc.dart deleted file mode 100644 index 8a2396b449a..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/on_exception_bloc.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -import '../counter/counter_bloc.dart'; - -class OnExceptionBloc extends Bloc { - OnExceptionBloc({ - required this.exception, - required this.onErrorCallback, - }) : super(0); - - final Function onErrorCallback; - final Exception exception; - - @override - void onError(Object error, StackTrace stackTrace) { - onErrorCallback(error, stackTrace); - super.onError(error, stackTrace); - } - - @override - Stream mapEventToState(CounterEvent event) async* { - throw exception; - } -} diff --git a/packages/bloc/test/legacy/blocs/counter/on_transition_error_bloc.dart b/packages/bloc/test/legacy/blocs/counter/on_transition_error_bloc.dart deleted file mode 100644 index be9ec166e79..00000000000 --- a/packages/bloc/test/legacy/blocs/counter/on_transition_error_bloc.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -import '../counter/counter_bloc.dart'; - -class OnTransitionErrorBloc extends Bloc { - OnTransitionErrorBloc({ - required this.error, - required this.onErrorCallback, - }) : super(0); - - final Function onErrorCallback; - final Error error; - - @override - void onError(Object error, StackTrace stackTrace) { - onErrorCallback(error, stackTrace); - super.onError(error, stackTrace); - } - - @override - void onTransition(Transition transition) { - super.onTransition(transition); - throw error; - } - - @override - Stream mapEventToState(CounterEvent event) async* { - switch (event) { - case CounterEvent.increment: - yield state + 1; - break; - case CounterEvent.decrement: - yield state - 1; - break; - } - } -} diff --git a/packages/bloc/test/legacy/blocs/seeded/seeded_bloc.dart b/packages/bloc/test/legacy/blocs/seeded/seeded_bloc.dart deleted file mode 100644 index 99b0b60784f..00000000000 --- a/packages/bloc/test/legacy/blocs/seeded/seeded_bloc.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:bloc/bloc.dart'; - -class SeededBloc extends Bloc { - SeededBloc({required this.seed, required this.states}) : super(seed); - - final List states; - final int seed; - - @override - Stream mapEventToState(String event) async* { - for (final state in states) { - yield state; - } - } -} diff --git a/packages/bloc/test/legacy/blocs/simple/simple_bloc.dart b/packages/bloc/test/legacy/blocs/simple/simple_bloc.dart deleted file mode 100644 index 3bbc217658b..00000000000 --- a/packages/bloc/test/legacy/blocs/simple/simple_bloc.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; - -class SimpleBloc extends Bloc { - SimpleBloc() : super(''); - - @override - Stream mapEventToState(dynamic event) async* { - yield 'data'; - } -}