-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: added the remote data source implementation (data/data_sourc…
…es) with test driven development & made the api_keys secret
- Loading branch information
Showing
9 changed files
with
1,220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
const String kNewsAPICategoryTechnology = "technology"; | ||
const String kNewsAPIBaseURL = "https://newsapi.org/v2/top-headlines"; | ||
const String kNewsAPICountry = "us"; |
24 changes: 24 additions & 0 deletions
24
lib/features/news_feed/data/data_sources/news_feed_remote_data_source.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,29 @@ | ||
import 'package:dio/dio.dart'; | ||
import 'package:news_app/core/configs/api/api_configs.dart'; | ||
import 'package:news_app/core/configs/api/api_keys.dart'; | ||
import 'package:news_app/core/error/exceptions.dart'; | ||
import 'package:news_app/features/news_feed/data/models/news_feed_model.dart'; | ||
|
||
abstract class NewsFeedRemoteDataSource { | ||
Future<NewsFeedModel> getNewsFeedForCategory(String category); | ||
} | ||
|
||
class NewsFeedRemoteDataSourceImpl extends NewsFeedRemoteDataSource { | ||
final Dio dio; | ||
|
||
NewsFeedRemoteDataSourceImpl(this.dio); | ||
|
||
@override | ||
Future<NewsFeedModel> getNewsFeedForCategory(String category) async { | ||
final queryParams = { | ||
"country": kNewsAPICountry, | ||
"apiKey": kNewsAPIKey, | ||
"category": category, | ||
}; | ||
final response = await dio.get(kNewsAPIBaseURL, queryParameters: queryParams); | ||
if (response.statusCode == 200) { | ||
return NewsFeedModel.fromJson(response.data); | ||
} | ||
throw ServerException(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
test/features/news_feed/data/data_sources/news_feed_remote_data_source_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import 'dart:convert'; | ||
|
||
import 'package:dio/dio.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
import 'package:mockito/annotations.dart'; | ||
import 'package:mockito/mockito.dart'; | ||
import 'package:news_app/core/configs/api/api_configs.dart'; | ||
import 'package:news_app/core/configs/api/api_keys.dart'; | ||
import 'package:news_app/core/error/exceptions.dart'; | ||
import 'package:news_app/features/news_feed/data/data_sources/news_feed_remote_data_source.dart'; | ||
import 'package:news_app/features/news_feed/data/models/news_feed_model.dart'; | ||
|
||
import '../../../../core/fixtures/fixture_file_reader.dart' | ||
as fixture_file_reader; | ||
import 'news_feed_remote_data_source_test.mocks.dart'; | ||
|
||
@GenerateNiceMocks([MockSpec<Dio>()]) | ||
void main() { | ||
late MockDio mockDio; | ||
late NewsFeedRemoteDataSourceImpl dataSourceImpl; | ||
|
||
setUp(() { | ||
mockDio = MockDio(); | ||
dataSourceImpl = NewsFeedRemoteDataSourceImpl(mockDio); | ||
}); | ||
|
||
Future<void> setUpMockDioSuccess200() async { | ||
when(mockDio.get(any, queryParameters: anyNamed('queryParameters'))) | ||
.thenAnswer((realInvocation) async => Response( | ||
data: jsonDecode(fixture_file_reader.fixture("news_feed.json")), | ||
statusCode: 200, | ||
requestOptions: RequestOptions(), | ||
)); | ||
} | ||
|
||
Future<void> setUpMockDioFailure400() async { | ||
when(mockDio.get(any, queryParameters: anyNamed('queryParameters'))) | ||
.thenAnswer((realInvocation) async => Response( | ||
statusCode: 404, | ||
requestOptions: RequestOptions(), | ||
)); | ||
} | ||
|
||
const testCategory = kNewsAPICategoryTechnology; | ||
const testNewsFeedModel = NewsFeedModel( | ||
status: "ok", | ||
totalResults: 1, | ||
articles: [ | ||
ArticlesModel( | ||
source: SourceModel( | ||
name: "Nintendo Life", | ||
), | ||
author: "Liam Doolan", | ||
title: | ||
"Metal Gear Solid: Master Collection Vol. 1 Resolution & Frame Rate Chart Released - Nintendo Life", | ||
description: "Here's how the Switch version compares", | ||
url: | ||
"https://www.nintendolife.com/news/2023/09/metal-gear-solid-master-collection-vol-1-resolution-and-frame-rate-chart-released", | ||
urlToImage: | ||
"https://images.nintendolife.com/9ae5106942e8a/1280x720.jpg", | ||
publishedAt: "2023-09-24T05:35:00Z", | ||
content: | ||
"Image: Konami\r\nHideo Kojima's legendary series Metal Gear Solid returns as a collection release this October on all platforms including the Nintendo Switch, and as part of this Konami has now shared … [+1295 chars]", | ||
) | ||
], | ||
); | ||
|
||
group("getNewsFeedForCategory tests", () { | ||
test( | ||
"should perform a GET request to a URL with specified category, country and apiKey", | ||
() async { | ||
//arrange | ||
//await setUpMockDioSuccess200(); | ||
when(mockDio.get(any, queryParameters: anyNamed('queryParameters'))) | ||
.thenAnswer((realInvocation) async => Response( | ||
data: jsonDecode(fixture_file_reader.fixture("news_feed.json")), | ||
statusCode: 200, | ||
requestOptions: RequestOptions(), | ||
)); | ||
|
||
const baseUrl = "https://newsapi.org/v2/top-headlines"; | ||
final queryParams = { | ||
"country": kNewsAPICountry, | ||
"apiKey": kNewsAPIKey, | ||
"category": testCategory, | ||
}; | ||
//act | ||
await dataSourceImpl.getNewsFeedForCategory(testCategory); | ||
|
||
//assert | ||
verify(mockDio.get(baseUrl, queryParameters: queryParams)); | ||
}); | ||
|
||
test("should return NewsFeedModel when the response code is 200 (success)", | ||
() async { | ||
//arrange | ||
await setUpMockDioSuccess200(); | ||
//act | ||
final result = await dataSourceImpl.getNewsFeedForCategory(testCategory); | ||
//assert | ||
expect(result, equals(testNewsFeedModel)); | ||
}); | ||
|
||
test( | ||
"should throw a server exception when the response code is other than 200 (eg: 404)", | ||
() async { | ||
//arrange | ||
await setUpMockDioFailure400(); | ||
//act | ||
final calledFunction = dataSourceImpl.getNewsFeedForCategory; | ||
//assert | ||
expect(() => calledFunction(testCategory), | ||
throwsA(const TypeMatcher<ServerException>())); | ||
}); | ||
}); | ||
} | ||
|
||
/* | ||
test("should",(){ | ||
//arrange | ||
//act | ||
//assert | ||
}); | ||
*/ |
Oops, something went wrong.