Skip to content

Commit 2f84c2c

Browse files
tddang-linagorahoangdat
authored andcommitted
Create CalendarEvent accept method
1 parent 351a1bf commit 2f84c2c

File tree

8 files changed

+362
-0
lines changed

8 files changed

+362
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:jmap_dart_client/jmap/core/id.dart';
2+
import 'package:jmap_dart_client/jmap/core/method/method.dart';
3+
import 'package:json_annotation/json_annotation.dart';
4+
5+
abstract class CalendarEventReplyMethod extends MethodRequiringAccountId
6+
with OptionalLanguage {
7+
CalendarEventReplyMethod(
8+
super.accountId,
9+
{
10+
required this.blobIds,
11+
});
12+
13+
final List<Id> blobIds;
14+
15+
@override
16+
List<Object?> get props => [accountId, blobIds, language];
17+
}
18+
19+
mixin OptionalLanguage {
20+
@JsonKey(includeIfNull: false)
21+
String? language;
22+
23+
void addLanguage(String value) {
24+
language = value;
25+
}
26+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import 'package:jmap_dart_client/jmap/core/id.dart';
2+
import 'package:jmap_dart_client/jmap/core/method/method_response.dart';
3+
4+
abstract class CalendarEventReplyResponse extends ResponseRequiringAccountId {
5+
CalendarEventReplyResponse(super.accountId, this.notFound);
6+
7+
final List<Id>? notFound;
8+
9+
@override
10+
List<Object?> get props => [accountId, notFound];
11+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import 'package:jmap_dart_client/http/converter/account_id_converter.dart';
2+
import 'package:jmap_dart_client/http/converter/id_converter.dart';
3+
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
4+
import 'package:jmap_dart_client/jmap/core/method/request/calendar_event_reply_method.dart';
5+
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
6+
import 'package:json_annotation/json_annotation.dart';
7+
8+
part 'calendar_event_accept_method.g.dart';
9+
10+
@JsonSerializable(converters: [
11+
AccountIdConverter(),
12+
IdConverter(),
13+
])
14+
class CalendarEventAcceptMethod extends CalendarEventReplyMethod {
15+
CalendarEventAcceptMethod(super.accountId, {required super.blobIds});
16+
17+
@override
18+
MethodName get methodName => MethodName('CalendarEvent/accept');
19+
20+
@override
21+
Set<CapabilityIdentifier> get requiredCapabilities => {
22+
CapabilityIdentifier.jmapCore,
23+
CapabilityIdentifier.jamesCalendarEvent
24+
};
25+
26+
@override
27+
Map<String, dynamic> toJson() => _$CalendarEventAcceptMethodToJson(this);
28+
}

lib/jmap/mail/calendar/reply/calendar_event_accept_method.g.dart

Lines changed: 33 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import 'package:jmap_dart_client/jmap/core/id.dart';
2+
import 'package:jmap_dart_client/jmap/core/method/response/calendar_event_reply_response.dart';
3+
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
4+
import 'package:jmap_dart_client/util/json_parsers.dart';
5+
6+
class CalendarEventAcceptResponse extends CalendarEventReplyResponse {
7+
CalendarEventAcceptResponse(
8+
super.accountId,
9+
super.notFound,
10+
{
11+
this.accepted,
12+
this.notCreated
13+
});
14+
15+
final List<EventId>? accepted;
16+
final List<Id>? notCreated;
17+
18+
static CalendarEventAcceptResponse deserialize(Map<String, dynamic> json) {
19+
return CalendarEventAcceptResponse(
20+
JsonParsers().parsingAccountId(json),
21+
JsonParsers().parsingListId(json, 'notFound'),
22+
accepted: JsonParsers().parsingListEventId(json, 'accepted'),
23+
notCreated: JsonParsers().parsingListId(json, 'notCreated'),
24+
);
25+
}
26+
27+
@override
28+
List<Object?> get props => [...super.props, accepted, notCreated];
29+
}

lib/util/json_parsers.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'package:jmap_dart_client/http/converter/account_id_converter.dart';
2+
import 'package:jmap_dart_client/http/converter/calendar/event_id_nullable_converter.dart';
3+
import 'package:jmap_dart_client/http/converter/id_converter.dart';
4+
import 'package:jmap_dart_client/jmap/account_id.dart';
5+
import 'package:jmap_dart_client/jmap/core/id.dart';
6+
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
7+
8+
class JsonParsers {
9+
const JsonParsers._();
10+
factory JsonParsers() => _instance;
11+
static const JsonParsers _instance = JsonParsers._();
12+
13+
AccountId parsingAccountId(Map<String, dynamic> json) {
14+
return const AccountIdConverter().fromJson(json['accountId'] as String);
15+
}
16+
17+
List<Id>? parsingListId(Map<String, dynamic> json, String key) {
18+
return (json[key] as List<dynamic>?)
19+
?.map((value) => const IdConverter().fromJson(value as String))
20+
.toList();
21+
}
22+
23+
List<EventId>? parsingListEventId(Map<String, dynamic> json, String key) {
24+
return (json[key] as List<dynamic>?)
25+
?.map((value) => const EventIdNullableConverter().fromJson(value as String))
26+
.where((element) => element != null)
27+
.cast<EventId>()
28+
.toList();
29+
}
30+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import 'package:dio/dio.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:http_mock_adapter/http_mock_adapter.dart';
4+
import 'package:jmap_dart_client/http/http_client.dart';
5+
import 'package:jmap_dart_client/jmap/account_id.dart';
6+
import 'package:jmap_dart_client/jmap/core/id.dart';
7+
import 'package:jmap_dart_client/jmap/core/method/request/calendar_event_reply_method.dart';
8+
import 'package:jmap_dart_client/jmap/core/method/response/calendar_event_reply_response.dart';
9+
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
10+
import 'package:jmap_dart_client/jmap/jmap_request.dart';
11+
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
12+
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_method.dart';
13+
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_response.dart';
14+
15+
void main() {
16+
final baseOption = BaseOptions(method: 'POST');
17+
final dio = Dio(baseOption)..options.baseUrl = 'http://domain.com/jmap';
18+
final dioAdapter = DioAdapter(dio: dio);
19+
final dioAdapterHeaders = {"accept": "application/json;jmapVersion=rfc-8621"};
20+
final httpClient = HttpClient(dio);
21+
final processingInvocation = ProcessingInvocation();
22+
final requestBuilder = JmapRequestBuilder(httpClient, processingInvocation);
23+
final accountId = AccountId(Id('123abc'));
24+
final successBlobId = Id('abc123');
25+
final failureBlobId = Id('def456');
26+
final notFoundBlobId = Id('ghi789');
27+
final blobIds = [successBlobId, failureBlobId, notFoundBlobId];
28+
final methodCallId = MethodCallId('c0');
29+
30+
Map<String, dynamic> constructData(CalendarEventReplyMethod method) => {
31+
"using": method.requiredCapabilities
32+
.map((capability) => capability.value.toString())
33+
.toList(),
34+
"methodCalls": [
35+
[
36+
method.methodName.value,
37+
{
38+
"accountId": accountId.id.value,
39+
"blobIds": blobIds.map((id) => id.value).toList(),
40+
},
41+
methodCallId.value
42+
]
43+
]
44+
};
45+
46+
Map<String, dynamic> constructResponse(CalendarEventReplyMethod method) => {
47+
"sessionState": "abcdefghij",
48+
"methodResponses": [[
49+
method.methodName.value,
50+
{
51+
"accountId": accountId.id.value,
52+
"accepted": [successBlobId.value],
53+
"notCreated": [failureBlobId.value],
54+
"notFound": [notFoundBlobId.value],
55+
},
56+
methodCallId.value
57+
]]
58+
};
59+
60+
group('calendar event accept method', () {
61+
final method = CalendarEventAcceptMethod(accountId, blobIds: blobIds);
62+
63+
test('should succeed with success blob data, '
64+
'and fail with failure blob data '
65+
'and not found with not found blob data', () async {
66+
// arrange
67+
final invocation = requestBuilder.invocation(method, methodCallId: methodCallId);
68+
dioAdapter.onPost(
69+
'',
70+
(server) => server.reply(200, constructResponse(method)),
71+
data: constructData(method),
72+
headers: dioAdapterHeaders,
73+
);
74+
75+
// act
76+
final response = (await (requestBuilder..usings(method.requiredCapabilities))
77+
.build()
78+
.execute())
79+
.parse<CalendarEventReplyResponse>(
80+
invocation.methodCallId,
81+
CalendarEventAcceptResponse.deserialize);
82+
83+
// assert
84+
expect((response as CalendarEventAcceptResponse?)?.accepted, equals([EventId(successBlobId.value)]));
85+
expect(response?.notCreated, equals([failureBlobId]));
86+
expect(response?.notFound, equals([notFoundBlobId]));
87+
});
88+
});
89+
}

test/util/json_parsers_test.dart

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:jmap_dart_client/jmap/account_id.dart';
3+
import 'package:jmap_dart_client/jmap/core/id.dart';
4+
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
5+
import 'package:jmap_dart_client/util/json_parsers.dart';
6+
7+
void main() {
8+
final jsonParsers = JsonParsers();
9+
10+
group('json parsers test:', () {
11+
group('parse account id test:', () {
12+
test('should return account id when json contains account id',() {
13+
// arrange
14+
const rawAccountId = 'abc123';
15+
final json = {'accountId': rawAccountId};
16+
17+
// act
18+
final accountId = jsonParsers.parsingAccountId(json);
19+
20+
// assert
21+
expect(accountId, AccountId(Id(rawAccountId)));
22+
});
23+
24+
test('should throw TypeError exception when json doesn\'t contains account id',() {
25+
// arrange
26+
final json = <String, dynamic>{};
27+
28+
// assert
29+
expect(
30+
() => jsonParsers.parsingAccountId(json),
31+
throwsA(isA<TypeError>()));
32+
});
33+
34+
test('should throw TypeError exception when accountId json is not String',() {
35+
// arrange
36+
const rawAccountId = 'abc123';
37+
final json = {'accountId': [rawAccountId]};
38+
39+
// assert
40+
expect(
41+
() => jsonParsers.parsingAccountId(json),
42+
throwsA(isA<TypeError>()));
43+
});
44+
});
45+
46+
group('parse list id test:', () {
47+
test('should return list id when json contains list id',() {
48+
// arrange
49+
const rawListId = ['abc123'];
50+
final json = {'listId': rawListId};
51+
52+
// act
53+
final listId = jsonParsers.parsingListId(json, 'listId');
54+
55+
// assert
56+
expect(listId, rawListId.map((id) => Id(id)).toList());
57+
});
58+
59+
test('should return null when json doesn\'t contains list id',() {
60+
// arrange
61+
final json = <String, dynamic>{};
62+
63+
// act
64+
final listId = jsonParsers.parsingListId(json, 'listId');
65+
66+
// assert
67+
expect(listId, null);
68+
});
69+
70+
test('should throw TypeError when list id json is not List<String>',() {
71+
// arrange
72+
final json = {'listId': 'abc123'};
73+
74+
// assert
75+
expect(
76+
() => jsonParsers.parsingListEventId(json, 'listId'),
77+
throwsA(isA<TypeError>()));
78+
});
79+
});
80+
81+
group('parse list event id test:', () {
82+
test('should return list event id when json contains list event id',() {
83+
// arrange
84+
const rawListEventId = ['abc123'];
85+
final json = {'listEventId': rawListEventId};
86+
87+
// act
88+
final listEventId = jsonParsers.parsingListEventId(json, 'listEventId');
89+
90+
// assert
91+
expect(listEventId, rawListEventId.map((id) => EventId(id)).toList());
92+
});
93+
94+
test('should return null when json doesn\'t contains list event id',() {
95+
// arrange
96+
final json = <String, dynamic>{};
97+
98+
// act
99+
final listEventId = jsonParsers.parsingListEventId(json, 'listEventId');
100+
101+
// assert
102+
expect(listEventId, null);
103+
});
104+
105+
test('should throw TypeError when list event id json is not List<String>',() {
106+
// arrange
107+
final json = {'listEventId': 'abc123'};
108+
109+
// assert
110+
expect(
111+
() => jsonParsers.parsingListEventId(json, 'listEventId'),
112+
throwsA(isA<TypeError>()));
113+
});
114+
});
115+
});
116+
}

0 commit comments

Comments
 (0)