Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds bloc implementation #7

Merged
merged 1 commit into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/core/utils/string_constants.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const String serverErrorMessage = "Server error, please try agian later!";
27 changes: 27 additions & 0 deletions lib/features/home/presentation/bloc/unsplash_image_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:unplash_sample/core/utils/string_constants.dart';
import 'package:unplash_sample/features/home/domain/entities/image.dart';
import 'package:unplash_sample/features/home/domain/usecases/fetch_images.dart';

part 'unsplash_image_event.dart';
part 'unsplash_image_state.dart';

class UnsplashImageBloc extends Bloc<UnsplashImageEvent, UnsplashImageState> {
final FetchImages fetchImages;

UnsplashImageBloc(this.fetchImages) : super(UnsplashImageInitialState()) {
on<UnsplashImageEvent>((event, emit) async {
if (event is FetchImageEvent) {
emit(UnsplashImageLoadingState());

final imagesEither = await fetchImages(event.params);
imagesEither.fold((error) {
emit(const UnsplashImageErrorState(serverErrorMessage));
}, (images) {
emit(UnsplashImageLoadedState(images));
});
}
});
}
}
17 changes: 17 additions & 0 deletions lib/features/home/presentation/bloc/unsplash_image_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
part of 'unsplash_image_bloc.dart';

abstract class UnsplashImageEvent extends Equatable {
const UnsplashImageEvent();

@override
List<Object> get props => [];

Check warning on line 7 in lib/features/home/presentation/bloc/unsplash_image_event.dart

View check run for this annotation

Codecov / codecov/patch

lib/features/home/presentation/bloc/unsplash_image_event.dart#L6-L7

Added lines #L6 - L7 were not covered by tests
}

class FetchImageEvent extends UnsplashImageEvent {
final FetchImageParams params;

const FetchImageEvent(this.params);

@override
List<Object> get props => [params.page, params.perPage];

Check warning on line 16 in lib/features/home/presentation/bloc/unsplash_image_event.dart

View check run for this annotation

Codecov / codecov/patch

lib/features/home/presentation/bloc/unsplash_image_event.dart#L15-L16

Added lines #L15 - L16 were not covered by tests
}
30 changes: 30 additions & 0 deletions lib/features/home/presentation/bloc/unsplash_image_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
part of 'unsplash_image_bloc.dart';

abstract class UnsplashImageState extends Equatable {
const UnsplashImageState();

@override
List<Object> get props => [];
}

class UnsplashImageInitialState extends UnsplashImageState {}

class UnsplashImageLoadingState extends UnsplashImageState {}

class UnsplashImageLoadedState extends UnsplashImageState {
final List<UnsplashImage> images;

const UnsplashImageLoadedState(this.images);

@override
List<Object> get props => [images];
}

class UnsplashImageErrorState extends UnsplashImageState {
final String errorMessage;

const UnsplashImageErrorState(this.errorMessage);

@override
List<Object> get props => [errorMessage];
}
8 changes: 8 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.11.0"
bloc:
dependency: "direct main"
description:
name: bloc
sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49"
url: "https://pub.dev"
source: hosted
version: "8.1.2"
boolean_selector:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ environment:
dependencies:
flutter:
sdk: flutter
bloc: ^8.1.2
dartz: ^0.10.1
dio: ^5.3.0
equatable: ^2.0.5
Expand Down
6 changes: 6 additions & 0 deletions test/core/mocks/fetch_images_mock.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'package:mocktail/mocktail.dart';
import 'package:unplash_sample/features/home/domain/usecases/fetch_images.dart';

class FetchImagesMock extends Mock implements FetchImages {}

class FakeFetchImageParams extends Fake implements FetchImageParams {}
77 changes: 77 additions & 0 deletions test/features/home/presentation/bloc/unsplash_image_bloc_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'dart:convert';

import 'package:bloc/bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:unplash_sample/core/error/error.dart';
import 'package:unplash_sample/core/utils/string_constants.dart';
import 'package:unplash_sample/features/home/data/models/image_model.dart';
import 'package:unplash_sample/features/home/domain/usecases/fetch_images.dart';
import 'package:unplash_sample/features/home/presentation/bloc/unsplash_image_bloc.dart';

import '../../../../core/mocks/fetch_images_mock.dart';
import '../../../../fixtures/fixture_reader.dart';

void main() {
late final FetchImagesMock fetchImagesMock;
late final Bloc bloc;
late final FetchImageParams params;

group("UnsplashImageBloc test", () {
setUpAll(() {
fetchImagesMock = FetchImagesMock();
bloc = UnsplashImageBloc(fetchImagesMock);
params = FetchImageParams(1, 20);

registerFallbackValue(FakeFetchImageParams());
});

test("Initial state should be UnsplashImageInitialState", () {
expect(bloc.state, UnsplashImageInitialState());
});

test(
"Emits [UnsplashImageLoadingState, UnsplashImageErrroState] on error",
() {
when(() => fetchImagesMock.call(any())).thenAnswer((invocation) async {
return Left(ServerError());
});

bloc.add(FetchImageEvent(params));

expectLater(
bloc.stream,
emitsInOrder([
UnsplashImageLoadingState(),
const UnsplashImageErrorState(serverErrorMessage),
]),
);
},
);

test(
"Emits [UnsplashImageLoadingState, UnsplashImageLoadedState] on success",
() {
final imageListModel =
UnsplashImageListModel.fromJson(List<Map<String, dynamic>>.from(
jsonDecode(fixture("image_model_fixture.json")),
));

when(() => fetchImagesMock.call(any())).thenAnswer((invocation) async {
return Right(imageListModel.images);
});

bloc.add(FetchImageEvent(params));

expectLater(
bloc.stream,
emitsInOrder([
UnsplashImageLoadingState(),
UnsplashImageLoadedState(imageListModel.images),
]),
);
},
);
});
}
Loading