diff --git a/lib/features/number_trivia/data/datasources/number_trivia_locale_data_source copy.dart b/lib/features/number_trivia/data/datasources/number_trivia_locale_data_source.dart similarity index 100% rename from lib/features/number_trivia/data/datasources/number_trivia_locale_data_source copy.dart rename to lib/features/number_trivia/data/datasources/number_trivia_locale_data_source.dart diff --git a/lib/features/number_trivia/data/repositories/number_trivia_repository_impl.dart b/lib/features/number_trivia/data/repositories/number_trivia_repository_impl.dart index 65b12f6..993abd3 100644 --- a/lib/features/number_trivia/data/repositories/number_trivia_repository_impl.dart +++ b/lib/features/number_trivia/data/repositories/number_trivia_repository_impl.dart @@ -1,12 +1,15 @@ import 'package:clean_arc/core/exceptions/exception.dart'; import 'package:clean_arc/core/platform/networrk_info.dart'; -import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_locale_data_source%20copy.dart'; +import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_locale_data_source.dart'; import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_remote_data_source.dart'; +import 'package:clean_arc/features/number_trivia/data/models/number_trivia_model.dart'; import 'package:clean_arc/features/number_trivia/domain/entities/number_trivia.dart'; import 'package:clean_arc/core/exceptions/failuers.dart'; import 'package:clean_arc/features/number_trivia/domain/repositories/number_trivia_repository.dart'; import 'package:dartz/dartz.dart'; +typedef Future _ConcreteOrRandomChooser(); + class NumberTriviaRepositoryImpl implements NumberTriviaRepository { final NumberTriviaRemoteDataSource remoteDataSource; final NumberTriviaLocaleDataSource localeDataSource; @@ -21,19 +24,33 @@ class NumberTriviaRepositoryImpl implements NumberTriviaRepository { @override Future> getConcreteNumberTrivia( int number) async { - networkInfo.isConnected; - try { - final remoteTrivia = - await remoteDataSource.getConcreteNumberTrivia(number); - await localeDataSource.cacheNumberTrivia(remoteTrivia); - return Right(remoteTrivia); - } on ServerException { - return Left(ServerFailure()); - } + return (await _getNumberTrivia( + () => remoteDataSource.getConcreteNumberTrivia(number))); } @override Future> getRandomNumberTrivia() async { - return Right(await remoteDataSource.getRandomNumberTrivia()); + return (await _getNumberTrivia( + () => remoteDataSource.getRandomNumberTrivia())); + } + + Future> _getNumberTrivia( + _ConcreteOrRandomChooser getConcreteOrRandomNumber) async { + if (await networkInfo.isConnected) { + try { + final trivia = await getConcreteOrRandomNumber(); + await localeDataSource.cacheNumberTrivia(trivia); + return Right(trivia); + } on ServerException { + return Left(ServerFailure()); + } + } else { + try { + final localeTrivia = await localeDataSource.getLastNumberTrivia(); + return Right(localeTrivia); + } on CacheException { + return Left(CacheFailure()); + } + } } } diff --git a/pubspec.lock b/pubspec.lock index 6acf805..ac006e5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -366,6 +366,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" meta: dependency: transitive description: @@ -608,7 +615,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.8" timing: dependency: transitive description: diff --git a/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.dart b/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.dart index 674c8b4..bf3d123 100644 --- a/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.dart +++ b/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.dart @@ -1,7 +1,7 @@ import 'package:clean_arc/core/exceptions/exception.dart'; import 'package:clean_arc/core/exceptions/failuers.dart'; import 'package:clean_arc/core/platform/networrk_info.dart'; -import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_locale_data_source%20copy.dart'; +import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_locale_data_source.dart'; import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_remote_data_source.dart'; import 'package:clean_arc/features/number_trivia/data/models/number_trivia_model.dart'; import 'package:clean_arc/features/number_trivia/data/repositories/number_trivia_repository_impl.dart'; @@ -32,6 +32,24 @@ void main() { ); }); + void runTestsOnline(Function body) { + group("device is online", () { + setUp(() { + when(mockNetworkInfo.isConnected).thenAnswer((_) async => true); + }); + body(); + }); + } + + void runTestsOffline(Function body) { + group("device is offline", () { + setUp(() { + when(mockNetworkInfo.isConnected).thenAnswer((_) async => false); + }); + body(); + }); + } + group("get concrete number trivia", () { const tNumber = 1; const tNumberTriviaModel = NumberTriviaModel(number: tNumber, text: "test"); @@ -47,11 +65,7 @@ void main() { verify(mockNetworkInfo.isConnected); }); - group("device is online", () { - setUp(() { - when(mockNetworkInfo.isConnected).thenAnswer((_) async => true); - }); - + runTestsOnline(() { test( 'should return remote data when the call to remote to data source is success', () async { @@ -99,7 +113,7 @@ void main() { }); }); - group("device is offline", () { + runTestsOffline(() { setUp(() { when(mockNetworkInfo.isConnected).thenAnswer((_) async => false); }); @@ -117,6 +131,119 @@ void main() { verify(mockNumberTriviaLocaleDataSource.getLastNumberTrivia()); expect(result, const Right(tNumberTrivia)); }); + + test('should return cache failure when there is not cached data present', + () async { + // arrange + when(mockNumberTriviaLocaleDataSource.getLastNumberTrivia()) + .thenThrow(CacheException()); + // act + final result = await repositoryImpl.getConcreteNumberTrivia(tNumber); + // assert + verifyZeroInteractions(mockNumberTriviaRemoteDataSource); + verify(mockNumberTriviaLocaleDataSource.getLastNumberTrivia()); + expect(result, equals(Left(CacheFailure()))); + }); + }); + }); + + + + group("get Random number trivia", () { + const tNumberTriviaModel = NumberTriviaModel(number: 123, text: "test"); + const NumberTrivia tNumberTrivia = tNumberTriviaModel; + test('should check if the device is online', () async { + // arrange + when(mockNetworkInfo.isConnected).thenAnswer((_) async => true); + when(mockNumberTriviaRemoteDataSource.getRandomNumberTrivia()) + .thenAnswer((_) async => tNumberTriviaModel); + // act + repositoryImpl.getRandomNumberTrivia(); + // assert + verify(mockNetworkInfo.isConnected); + }); + + runTestsOnline(() { + test( + 'should return remote data when the call to remote to data source is success', + () async { + // arrange + when(mockNumberTriviaRemoteDataSource.getRandomNumberTrivia()) + .thenAnswer((realInvocation) async => tNumberTriviaModel); + // act + final result = await repositoryImpl.getRandomNumberTrivia(); + // assert + + verify( + mockNumberTriviaRemoteDataSource.getRandomNumberTrivia()); + expect(result, equals(const Right(tNumberTrivia))); + }); + test( + 'should cached the data lacally when the call to remote to data source is success', + () async { + // arrange + when(mockNumberTriviaRemoteDataSource.getRandomNumberTrivia()) + .thenAnswer((realInvocation) async => tNumberTriviaModel); + // act + await repositoryImpl.getRandomNumberTrivia(); + // assert + + verify( + mockNumberTriviaRemoteDataSource.getRandomNumberTrivia()); + verify(mockNumberTriviaLocaleDataSource + .cacheNumberTrivia(tNumberTriviaModel)); + }); + + test( + 'should return server failure when the call to remote to data source is unsuccess', + () async { + // arrange + when(mockNumberTriviaRemoteDataSource.getRandomNumberTrivia()) + .thenThrow(ServerException()); + // act + final result = await repositoryImpl.getRandomNumberTrivia(); + // assert + + verify( + mockNumberTriviaRemoteDataSource.getRandomNumberTrivia()); + verifyZeroInteractions(mockNumberTriviaLocaleDataSource); + expect(result, equals(Left(ServerFailure()))); + }); + }); + + runTestsOffline(() { + setUp(() { + when(mockNetworkInfo.isConnected).thenAnswer((_) async => false); + }); + + test( + 'should return last cached locally data when the cache data is present', + () async { + // arrange + when(mockNumberTriviaLocaleDataSource.getLastNumberTrivia()) + .thenAnswer((realInvocation) async => tNumberTriviaModel); + // act + final result = await repositoryImpl.getRandomNumberTrivia(); + // assert + verifyZeroInteractions(mockNumberTriviaRemoteDataSource); + verify(mockNumberTriviaLocaleDataSource.getLastNumberTrivia()); + expect(result, const Right(tNumberTrivia)); + }); + + test('should return cache failure when there is not cached data present', + () async { + // arrange + when(mockNumberTriviaLocaleDataSource.getLastNumberTrivia()) + .thenThrow(CacheException()); + // act + final result = await repositoryImpl.getRandomNumberTrivia(); + // assert + verifyZeroInteractions(mockNumberTriviaRemoteDataSource); + verify(mockNumberTriviaLocaleDataSource.getLastNumberTrivia()); + expect(result, equals(Left(CacheFailure()))); + }); }); }); + + } diff --git a/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.mocks.dart b/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.mocks.dart index 2cfb0fd..2840472 100644 --- a/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.mocks.dart +++ b/test/features/number_trivia/data/repositories/number_trivia_repository_impl_test.mocks.dart @@ -5,7 +5,7 @@ import 'dart:async' as _i4; import 'package:clean_arc/core/platform/networrk_info.dart' as _i6; -import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_locale_data_source%20copy.dart' +import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_locale_data_source.dart' as _i5; import 'package:clean_arc/features/number_trivia/data/datasources/number_trivia_remote_data_source.dart' as _i3;