Skip to content

Commit 5ee2f1d

Browse files
committed
Buat implement function endpoint ping
Sekalian buat unit testnya.
1 parent 7524e0b commit 5ee2f1d

File tree

3 files changed

+250
-0
lines changed

3 files changed

+250
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import 'package:dio/dio.dart';
2+
import 'package:dipantau_desktop_client/core/error/failure.dart';
3+
import 'package:dipantau_desktop_client/core/network/network_info.dart';
4+
import 'package:dipantau_desktop_client/feature/data/datasource/general/general_remote_data_source.dart';
5+
import 'package:dipantau_desktop_client/feature/data/model/general/general_response.dart';
6+
import 'package:dipantau_desktop_client/feature/domain/repository/general/general_repository.dart';
7+
8+
class GeneralRepositoryImpl implements GeneralRepository {
9+
final GeneralRemoteDataSource remoteDataSource;
10+
final NetworkInfo networkInfo;
11+
12+
GeneralRepositoryImpl({
13+
required this.remoteDataSource,
14+
required this.networkInfo,
15+
});
16+
17+
String getErrorMessageFromEndpoint(dynamic dynamicErrorMessage, String httpErrorMessage, int? statusCode) {
18+
if (dynamicErrorMessage is Map && dynamicErrorMessage.containsKey('message')) {
19+
return '$statusCode ${dynamicErrorMessage['message']}';
20+
} else if (dynamicErrorMessage is String) {
21+
return httpErrorMessage;
22+
} else {
23+
return httpErrorMessage;
24+
}
25+
}
26+
27+
@override
28+
Future<({Failure? failure, GeneralResponse? response})> ping() async {
29+
Failure? failure;
30+
GeneralResponse? response;
31+
final isConnected = await networkInfo.isConnected;
32+
if (isConnected) {
33+
try {
34+
response = await remoteDataSource.ping();
35+
} on DioException catch (error) {
36+
final message = error.message ?? error.toString();
37+
if (error.response == null) {
38+
failure = ServerFailure(message);
39+
} else {
40+
final errorMessage = getErrorMessageFromEndpoint(
41+
error.response?.data,
42+
message,
43+
error.response?.statusCode,
44+
);
45+
failure = ServerFailure(errorMessage);
46+
}
47+
} on TypeError catch (error) {
48+
final errorMessage = error.toString();
49+
failure = ParsingFailure(errorMessage);
50+
}
51+
} else {
52+
failure = ConnectionFailure();
53+
}
54+
return (failure: failure, response: response);
55+
}
56+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import 'package:dipantau_desktop_client/core/error/failure.dart';
2+
import 'package:dipantau_desktop_client/feature/data/model/general/general_response.dart';
3+
4+
abstract class GeneralRepository {
5+
Future<({Failure? failure, GeneralResponse? response})> ping();
6+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import 'dart:convert';
2+
3+
import 'package:dio/dio.dart';
4+
import 'package:dipantau_desktop_client/core/error/failure.dart';
5+
import 'package:dipantau_desktop_client/feature/data/model/general/general_response.dart';
6+
import 'package:dipantau_desktop_client/feature/data/repository/general/general_repository_impl.dart';
7+
import 'package:flutter_test/flutter_test.dart';
8+
import 'package:mockito/mockito.dart';
9+
10+
import '../../../../fixture/fixture_reader.dart';
11+
import '../../../../helper/mock_helper.mocks.dart';
12+
13+
void main() {
14+
late GeneralRepositoryImpl repository;
15+
late MockGeneralRemoteDataSource mockRemoteDataSource;
16+
late MockNetworkInfo mockNetworkInfo;
17+
18+
setUp(() {
19+
mockRemoteDataSource = MockGeneralRemoteDataSource();
20+
mockNetworkInfo = MockNetworkInfo();
21+
repository = GeneralRepositoryImpl(
22+
remoteDataSource: mockRemoteDataSource,
23+
networkInfo: mockNetworkInfo,
24+
);
25+
});
26+
27+
final tRequestOptions = RequestOptions(path: '');
28+
29+
void setUpMockNetworkConnected() {
30+
when(mockNetworkInfo.isConnected).thenAnswer((_) async => true);
31+
}
32+
33+
void setUpMockNetworkDisconnected() {
34+
when(mockNetworkInfo.isConnected).thenAnswer((_) async => false);
35+
}
36+
37+
void testDisconnected(Function endpointInvoke) {
38+
test(
39+
'pastikan mengembalikan objek ConnectionFailure ketika device tidak terhubung ke internet',
40+
() async {
41+
// arrange
42+
setUpMockNetworkDisconnected();
43+
44+
// act
45+
final result = await endpointInvoke.call();
46+
47+
// assert
48+
verify(mockNetworkInfo.isConnected);
49+
expect(result.failure, ConnectionFailure());
50+
},
51+
);
52+
}
53+
54+
void testServerFailureString(Function whenInvoke, Function actInvoke, Function verifyInvoke) {
55+
test(
56+
'pastikan mengembalikan objek ServerFailure ketika repository menerima respon kegagalan '
57+
'dari endpoint dengan respon data html atau string',
58+
() async {
59+
// arrange
60+
setUpMockNetworkConnected();
61+
when(whenInvoke.call()).thenThrow(
62+
DioException(
63+
requestOptions: tRequestOptions,
64+
message: 'testError',
65+
response: Response(
66+
requestOptions: tRequestOptions,
67+
data: 'testDataError',
68+
statusCode: 400,
69+
),
70+
),
71+
);
72+
73+
// act
74+
final result = await actInvoke.call();
75+
76+
// assert
77+
verify(verifyInvoke.call());
78+
expect(result.failure, ServerFailure('testError'));
79+
},
80+
);
81+
}
82+
83+
void testParsingFailure(Function whenInvoke, Function actInvoke, Function verifyInvoke) {
84+
test(
85+
'pastikan mengembalikan objek ParsingFailure ketika RemoteDataSource menerima respon kegagalan '
86+
'dari endpoint',
87+
() async {
88+
// arrange
89+
setUpMockNetworkConnected();
90+
when(whenInvoke.call()).thenThrow(TypeError());
91+
92+
// act
93+
final result = await actInvoke.call();
94+
95+
// assert
96+
verify(verifyInvoke.call());
97+
expect(result.failure, ParsingFailure(TypeError().toString()));
98+
},
99+
);
100+
}
101+
102+
group('ping', () {
103+
final tResponse = GeneralResponse.fromJson(
104+
json.decode(
105+
fixture('general_response.json'),
106+
),
107+
);
108+
109+
test(
110+
'pastikan mengembalikan objek model GeneralResponse ketika RemoteDataSource berhasil menerima '
111+
'respon sukses dari endpoint',
112+
() async {
113+
// arrange
114+
setUpMockNetworkConnected();
115+
when(mockRemoteDataSource.ping()).thenAnswer((_) async => tResponse);
116+
117+
// act
118+
final result = await repository.ping();
119+
120+
// assert
121+
verify(mockRemoteDataSource.ping());
122+
expect(result.response, tResponse);
123+
},
124+
);
125+
126+
test(
127+
'pastikan mengembalikan objek ServerFailure ketika RemoteDataSource berhasil menerima '
128+
'respon timeout dari endpoint',
129+
() async {
130+
// arrange
131+
setUpMockNetworkConnected();
132+
when(mockRemoteDataSource.ping())
133+
.thenThrow(DioException(requestOptions: tRequestOptions, message: 'testError'));
134+
135+
// act
136+
final result = await repository.ping();
137+
138+
// assert
139+
verify(mockRemoteDataSource.ping());
140+
expect(result.failure, ServerFailure('testError'));
141+
},
142+
);
143+
144+
test(
145+
'pastikan mengembalikan objek ServerFailure ketika RemoteDataSource menerima respon kegagaln '
146+
'dari endpoint',
147+
() async {
148+
// arrange
149+
setUpMockNetworkConnected();
150+
when(mockRemoteDataSource.ping()).thenThrow(
151+
DioException(
152+
requestOptions: tRequestOptions,
153+
message: 'testError',
154+
response: Response(
155+
requestOptions: tRequestOptions,
156+
data: {
157+
'title': 'testTitleError',
158+
'message': 'testMessageError',
159+
},
160+
statusCode: 400,
161+
),
162+
),
163+
);
164+
165+
// act
166+
final result = await repository.ping();
167+
168+
// assert
169+
verify(mockRemoteDataSource.ping());
170+
expect(result.failure, ServerFailure('400 testMessageError'));
171+
},
172+
);
173+
174+
testServerFailureString(
175+
() => mockRemoteDataSource.ping(),
176+
() => repository.ping(),
177+
() => mockRemoteDataSource.ping(),
178+
);
179+
180+
testParsingFailure(
181+
() => mockRemoteDataSource.ping(),
182+
() => repository.ping(),
183+
() => mockRemoteDataSource.ping(),
184+
);
185+
186+
testDisconnected(() => repository.ping());
187+
});
188+
}

0 commit comments

Comments
 (0)