Skip to content

Commit 7a178b2

Browse files
committed
feat: Buat business logic fitur cron tracking didalam cron tracking bloc sekalian dengan event dan state-nya
Sekalian buat unit test-nya juga.
1 parent 39b7a98 commit 7a178b2

7 files changed

Lines changed: 273 additions & 0 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import 'dart:async';
2+
3+
import 'package:bloc/bloc.dart';
4+
import 'package:bloc_concurrency/bloc_concurrency.dart';
5+
import 'package:dipantau_desktop_client/core/util/helper.dart';
6+
import 'package:dipantau_desktop_client/feature/data/model/create_track/bulk_create_track_data_body.dart';
7+
import 'package:dipantau_desktop_client/feature/data/model/create_track/bulk_create_track_image_body.dart';
8+
import 'package:dipantau_desktop_client/feature/domain/usecase/bulk_create_track_data/bulk_create_track_data.dart';
9+
import 'package:dipantau_desktop_client/feature/domain/usecase/bulk_create_track_image/bulk_create_track_image.dart';
10+
11+
part 'cron_tracking_event.dart';
12+
13+
part 'cron_tracking_state.dart';
14+
15+
class CronTrackingBloc extends Bloc<CronTrackingEvent, CronTrackingState> {
16+
final Helper helper;
17+
final BulkCreateTrackData bulkCreateTrackData;
18+
final BulkCreateTrackImage bulkCreateTrackImage;
19+
20+
CronTrackingBloc({
21+
required this.helper,
22+
required this.bulkCreateTrackData,
23+
required this.bulkCreateTrackImage,
24+
}) : super(InitialCronTrackingState()) {
25+
on<RunCronTrackingEvent>(_onRunCronTrackingEvent, transformer: restartable());
26+
}
27+
28+
FutureOr<void> _onRunCronTrackingEvent(
29+
RunCronTrackingEvent event,
30+
Emitter<CronTrackingState> emit,
31+
) async {
32+
final bodyData = event.bodyData;
33+
final ids = <int>[];
34+
if (bodyData != null) {
35+
final result = await bulkCreateTrackData(
36+
ParamsBulkCreateTrackData(
37+
body: bodyData,
38+
),
39+
);
40+
if (result.response != null) {
41+
ids.addAll(bodyData.data.where((element) => element.id != null).map((e) => e.id!));
42+
}
43+
}
44+
45+
final bodyImage = event.bodyImage;
46+
final files = <String>[];
47+
if (bodyImage != null) {
48+
final result = await bulkCreateTrackImage(
49+
ParamsBulkCreateTrackImage(
50+
body: bodyImage,
51+
),
52+
);
53+
if (result.response != null) {
54+
files.addAll(bodyImage.files);
55+
}
56+
}
57+
emit(
58+
SuccessRunCronTrackingState(
59+
ids: ids,
60+
files: files,
61+
),
62+
);
63+
}
64+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
part of 'cron_tracking_bloc.dart';
2+
3+
abstract class CronTrackingEvent {}
4+
5+
class RunCronTrackingEvent extends CronTrackingEvent {
6+
final BulkCreateTrackDataBody? bodyData;
7+
final BulkCreateTrackImageBody? bodyImage;
8+
9+
RunCronTrackingEvent({
10+
required this.bodyData,
11+
required this.bodyImage,
12+
});
13+
14+
@override
15+
String toString() {
16+
return 'RunCronTrackingEvent{bodyData: $bodyData, bodyImage: $bodyImage}';
17+
}
18+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
part of 'cron_tracking_bloc.dart';
2+
3+
abstract class CronTrackingState {}
4+
5+
class InitialCronTrackingState extends CronTrackingState {}
6+
7+
class LoadingCronTrackingState extends CronTrackingState {}
8+
9+
class FailureCronTrackingState extends CronTrackingState {
10+
final String errorMessage;
11+
12+
FailureCronTrackingState({
13+
required this.errorMessage,
14+
});
15+
16+
@override
17+
String toString() {
18+
return 'FailureCronTrackingState{errorMessage: $errorMessage}';
19+
}
20+
}
21+
22+
class SuccessRunCronTrackingState extends CronTrackingState {
23+
final List<int> ids;
24+
final List<String> files;
25+
26+
SuccessRunCronTrackingState({
27+
required this.ids,
28+
required this.files,
29+
});
30+
31+
@override
32+
String toString() {
33+
return 'SuccessRunCronTrackingState{ids: $ids, files: $files}';
34+
}
35+
}

lib/injection_container.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import 'package:dipantau_desktop_client/feature/domain/usecase/set_kv_setting/se
3737
import 'package:dipantau_desktop_client/feature/domain/usecase/sign_up/sign_up.dart';
3838
import 'package:dipantau_desktop_client/feature/domain/usecase/update_user/update_user.dart';
3939
import 'package:dipantau_desktop_client/feature/presentation/bloc/appearance/appearance_bloc.dart';
40+
import 'package:dipantau_desktop_client/feature/presentation/bloc/cron_tracking/cron_tracking_bloc.dart';
4041
import 'package:dipantau_desktop_client/feature/presentation/bloc/home/home_bloc.dart';
4142
import 'package:dipantau_desktop_client/feature/presentation/bloc/login/login_bloc.dart';
4243
import 'package:dipantau_desktop_client/feature/presentation/bloc/member/member_bloc.dart';
@@ -123,6 +124,13 @@ void init() {
123124
bulkCreateTrackData: sl(),
124125
),
125126
);
127+
sl.registerFactory(
128+
() => CronTrackingBloc(
129+
helper: sl(),
130+
bulkCreateTrackData: sl(),
131+
bulkCreateTrackImage: sl(),
132+
),
133+
);
126134

127135
// use case
128136
sl.registerLazySingleton(() => GetProject(repository: sl()));
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import 'dart:convert';
2+
3+
import 'package:bloc_test/bloc_test.dart';
4+
import 'package:dipantau_desktop_client/feature/data/model/create_track/bulk_create_track_data_body.dart';
5+
import 'package:dipantau_desktop_client/feature/data/model/create_track/bulk_create_track_image_body.dart';
6+
import 'package:dipantau_desktop_client/feature/data/model/general/general_response.dart';
7+
import 'package:dipantau_desktop_client/feature/domain/usecase/bulk_create_track_data/bulk_create_track_data.dart';
8+
import 'package:dipantau_desktop_client/feature/domain/usecase/bulk_create_track_image/bulk_create_track_image.dart';
9+
import 'package:dipantau_desktop_client/feature/presentation/bloc/cron_tracking/cron_tracking_bloc.dart';
10+
import 'package:flutter_test/flutter_test.dart';
11+
import 'package:mockito/mockito.dart';
12+
13+
import '../../../../fixture/fixture_reader.dart';
14+
import '../../../../helper/mock_helper.mocks.dart';
15+
16+
void main() {
17+
late CronTrackingBloc bloc;
18+
late MockHelper mockHelper;
19+
late MockBulkCreateTrackData mockBulkCreateTrackData;
20+
late MockBulkCreateTrackImage mockBulkCreateTrackImage;
21+
22+
setUp(() {
23+
mockHelper = MockHelper();
24+
mockBulkCreateTrackData = MockBulkCreateTrackData();
25+
mockBulkCreateTrackImage = MockBulkCreateTrackImage();
26+
bloc = CronTrackingBloc(
27+
helper: mockHelper,
28+
bulkCreateTrackData: mockBulkCreateTrackData,
29+
bulkCreateTrackImage: mockBulkCreateTrackImage,
30+
);
31+
});
32+
33+
test(
34+
'pastikan output dari initialState',
35+
() async {
36+
// assert
37+
expect(
38+
bloc.state,
39+
isA<InitialCronTrackingState>(),
40+
);
41+
},
42+
);
43+
44+
group('run cron tracking', () {
45+
final bodyData = BulkCreateTrackDataBody.fromJson(
46+
json.decode(
47+
fixture('bulk_create_track_data_body.json'),
48+
),
49+
);
50+
final bodyImage = BulkCreateTrackImageBody.fromJson(
51+
json.decode(
52+
fixture('bulk_create_track_image_body.json'),
53+
),
54+
);
55+
final tEvent = RunCronTrackingEvent(
56+
bodyData: bodyData,
57+
bodyImage: bodyImage,
58+
);
59+
final paramsData = ParamsBulkCreateTrackData(body: bodyData);
60+
final paramsImage = ParamsBulkCreateTrackImage(body: bodyImage);
61+
final tResponse = GeneralResponse.fromJson(
62+
json.decode(
63+
fixture('general_response.json'),
64+
),
65+
);
66+
67+
blocTest(
68+
'pastikan emit [SuccessRunCronTrackingState] ketika terima event RunCronTrackingEvent dengan proses berhasil',
69+
build: () {
70+
final result = (failure: null, response: tResponse);
71+
when(mockBulkCreateTrackData(any)).thenAnswer((_) async => result);
72+
when(mockBulkCreateTrackImage(any)).thenAnswer((_) async => result);
73+
return bloc;
74+
},
75+
act: (CronTrackingBloc bloc) {
76+
return bloc.add(tEvent);
77+
},
78+
expect: () => [
79+
isA<SuccessRunCronTrackingState>(),
80+
],
81+
verify: (_) {
82+
verify(mockBulkCreateTrackData(paramsData));
83+
verify(mockBulkCreateTrackImage(paramsImage));
84+
},
85+
);
86+
});
87+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'package:dipantau_desktop_client/feature/presentation/bloc/cron_tracking/cron_tracking_bloc.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
4+
void main() {
5+
group('RunCronTrackingEvent', () {
6+
final tEvent = RunCronTrackingEvent(
7+
bodyData: null,
8+
bodyImage: null,
9+
);
10+
11+
test(
12+
'pastikan output dari fungsi toString',
13+
() async {
14+
// assert
15+
expect(
16+
tEvent.toString(),
17+
'RunCronTrackingEvent{bodyData: ${tEvent.bodyData}, bodyImage: ${tEvent.bodyImage}}',
18+
);
19+
},
20+
);
21+
});
22+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import 'package:dipantau_desktop_client/feature/presentation/bloc/cron_tracking/cron_tracking_bloc.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
4+
void main() {
5+
group('FailureCronTrackingState', () {
6+
final tState = FailureCronTrackingState(
7+
errorMessage: 'testErrorMessage',
8+
);
9+
10+
test(
11+
'pastikan output dari fungsi toString',
12+
() async {
13+
// assert
14+
expect(
15+
tState.toString(),
16+
'FailureCronTrackingState{errorMessage: ${tState.errorMessage}}',
17+
);
18+
},
19+
);
20+
});
21+
22+
group('SuccessRunCronTrackingState', () {
23+
final tState = SuccessRunCronTrackingState(
24+
ids: [],
25+
files: [],
26+
);
27+
28+
test(
29+
'pastikan output dari fungsi toString',
30+
() async {
31+
// assert
32+
expect(
33+
tState.toString(),
34+
'SuccessRunCronTrackingState{ids: ${tState.ids}, files: ${tState.files}}',
35+
);
36+
},
37+
);
38+
});
39+
}

0 commit comments

Comments
 (0)