Skip to content

Commit

Permalink
Create news remote data source
Browse files Browse the repository at this point in the history
  • Loading branch information
CoderJava committed Apr 14, 2020
1 parent 69db696 commit b71406b
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 4 deletions.
4 changes: 2 additions & 2 deletions lib/config/base_url_config.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class BaseUrlConfig {
final String baseUrlDevelopment = 'https://bengkelrobot.net:8003/v2';
final String baseUrlProduction = 'https://newsapi.org/v2';
final String baseUrlDevelopment = 'https://bengkelrobot.net:8003';
final String baseUrlProduction = 'https://newsapi.org';
}
3 changes: 3 additions & 0 deletions lib/config/constant_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class ConstantConfig {
final String apiKeyNewsApi = '3f1bdb0927c94f8da5708f7a36f7d06f';
}
37 changes: 37 additions & 0 deletions lib/feature/data/datasource/news/news_remote_data_source.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:dio/dio.dart';
import 'package:flutter_news_app/config/constant_config.dart';
import 'package:flutter_news_app/feature/data/model/topheadlinesnews/top_headlines_news_response_model.dart';
import 'package:meta/meta.dart';

abstract class NewsRemoteDataSource {
/// Calls the baseUrl:/v2/top-headlines?country=:country&apiKey=:apiKey endpoint
///
/// Throws a [DioError] for all error codes.
Future<TopHeadlinesNewsResponseModel> getTopHeadlinesNews();
}

class NewsRemoteDataSourceImpl implements NewsRemoteDataSource {
final Dio dio;
final ConstantConfig constantConfig;

NewsRemoteDataSourceImpl({
@required this.dio,
@required this.constantConfig,
});

@override
Future<TopHeadlinesNewsResponseModel> getTopHeadlinesNews() async {
var response = await dio.get(
'/v2/top-headlines',
queryParameters: {
'country': 'id',
'apiKey': constantConfig.apiKeyNewsApi,
},
);
if (response.statusCode == 200) {
return TopHeadlinesNewsResponseModel.fromJson(response.data);
} else {
throw DioError();
}
}
}
117 changes: 117 additions & 0 deletions test/feature/data/datasource/news/news_remote_data_source_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter_news_app/config/base_url_config.dart';
import 'package:flutter_news_app/config/constant_config.dart';
import 'package:flutter_news_app/feature/data/datasource/news/news_remote_data_source.dart';
import 'package:flutter_news_app/feature/data/model/topheadlinesnews/top_headlines_news_response_model.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:matcher/matcher.dart';
import 'package:mockito/mockito.dart';

import '../../../../fixture/fixture_reader.dart';

class MockDioAdapter extends Mock implements HttpClientAdapter {}

class MockDio extends Mock implements Dio {}

void main() {
NewsRemoteDataSourceImpl newsRemoteDataSource;
ConstantConfig constantConfig;
MockDio mockDio;
MockDioAdapter mockDioAdapter;

setUp(() {
mockDio = MockDio();
constantConfig = ConstantConfig();
mockDioAdapter = MockDioAdapter();
mockDio.httpClientAdapter = mockDioAdapter;
mockDio.options = BaseOptions(
baseUrl: BaseUrlConfig().baseUrlDevelopment,
);
newsRemoteDataSource = NewsRemoteDataSourceImpl(
dio: mockDio,
constantConfig: constantConfig,
);
});

group('getTopHeadlinesNews', () {
final tTopHeadlinesNewsResponseModel = TopHeadlinesNewsResponseModel.fromJson(
json.decode(
fixture('top_headlines_news_response_model.json'),
),
);

void setUpMockDioSuccess() {
final responsePayload = json.decode(fixture('top_headlines_news_response_model.json'));
final response = Response(
data: responsePayload,
statusCode: 200,
headers: Headers.fromMap({
Headers.contentTypeHeader: [Headers.jsonContentType],
}),
);
when(
mockDio.get(
any,
queryParameters: anyNamed('queryParameters'),
),
).thenAnswer((_) async => response);
}

test(
'make sure there is a GET request to endpoint /v2/top-headlines?country=:country&apiKey=:apiKey',
() async {
// arrange
setUpMockDioSuccess();

// act
await newsRemoteDataSource.getTopHeadlinesNews();

// assert
verify(
mockDio.get(
'/v2/top-headlines',
queryParameters: {
'country': 'id',
'apiKey': constantConfig.apiKeyNewsApi,
},
),
);
},
);

test(
'make sure to return the TopHeadlinesNewsResponseModel object when the '
'response code is successful from the endpoint',
() async {
// arrange
setUpMockDioSuccess();

// act
final result = await newsRemoteDataSource.getTopHeadlinesNews();

// assert
expect(result, tTopHeadlinesNewsResponseModel);
},
);

test(
'make sure to receive DioError when the response code fails from the endpoint',
() async {
// arrange
final response = Response(
data: 'Bad Request',
statusCode: 400,
);
when(mockDio.get(any, queryParameters: anyNamed('queryParameters'))).thenAnswer((_) async => response);

// act
final call = newsRemoteDataSource.getTopHeadlinesNews();

// assert
expect(() => call, throwsA(TypeMatcher<DioError>()));
},
);
});
}
2 changes: 0 additions & 2 deletions test/fixture/fixture_reader.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import 'dart:io';

final baseUrlTest = 'https://bengkelrobot.net:8003/v2';

String fixture(String name) {
var currentDirectory = Directory.current.toString().replaceAll('\'', '');
var lastDirectory = currentDirectory.split('/')[currentDirectory.split('/').length - 1];
Expand Down

0 comments on commit b71406b

Please sign in to comment.