Skip to content

Commit

Permalink
Create CalendarEvent accept method
Browse files Browse the repository at this point in the history
  • Loading branch information
tddang-linagora authored and hoangdat committed May 2, 2024
1 parent 43e9ae9 commit f737823
Show file tree
Hide file tree
Showing 8 changed files with 376 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/jmap/core/method/request/calendar_event_reply_method.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/method.dart';
import 'package:json_annotation/json_annotation.dart';

abstract class CalendarEventReplyMethod extends MethodRequiringAccountId
with OptionalLanguage {
CalendarEventReplyMethod(
super.accountId,
{
required this.blobIds,
});

final List<Id> blobIds;

@override
List<Object?> get props => [accountId, blobIds, language];
}

mixin OptionalLanguage {
@JsonKey(includeIfNull: false)
String? language;

void addLanguage(String value) {
language = value;
}
}
11 changes: 11 additions & 0 deletions lib/jmap/core/method/response/calendar_event_reply_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/method_response.dart';

abstract class CalendarEventReplyResponse extends ResponseRequiringAccountId {
CalendarEventReplyResponse(super.accountId, this.notFound);

final List<Id>? notFound;

@override
List<Object?> get props => [accountId, notFound];
}
28 changes: 28 additions & 0 deletions lib/jmap/mail/calendar/reply/calendar_event_accept_method.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:jmap_dart_client/http/converter/account_id_converter.dart';
import 'package:jmap_dart_client/http/converter/id_converter.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
import 'package:jmap_dart_client/jmap/core/method/request/calendar_event_reply_method.dart';
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
import 'package:json_annotation/json_annotation.dart';

part 'calendar_event_accept_method.g.dart';

@JsonSerializable(converters: [
AccountIdConverter(),
IdConverter(),
])
class CalendarEventAcceptMethod extends CalendarEventReplyMethod {
CalendarEventAcceptMethod(super.accountId, {required super.blobIds});

@override
MethodName get methodName => MethodName('CalendarEvent/accept');

@override
Set<CapabilityIdentifier> get requiredCapabilities => {
CapabilityIdentifier.jmapCore,
CapabilityIdentifier.jamesCalendarEvent
};

@override
Map<String, dynamic> toJson() => _$CalendarEventAcceptMethodToJson(this);
}
33 changes: 33 additions & 0 deletions lib/jmap/mail/calendar/reply/calendar_event_accept_method.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions lib/jmap/mail/calendar/reply/calendar_event_accept_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/response/calendar_event_reply_response.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
import 'package:jmap_dart_client/util/json_parsers.dart';

class CalendarEventAcceptResponse extends CalendarEventReplyResponse {
CalendarEventAcceptResponse(
super.accountId,
super.notFound,
{
this.accepted,
this.notCreated
});

final List<EventId>? accepted;
final List<Id>? notCreated;

static CalendarEventAcceptResponse deserialize(Map<String, dynamic> json) {
return CalendarEventAcceptResponse(
JsonParsers().parsingAccountId(json),
JsonParsers().parsingListId(json, 'notFound'),
accepted: JsonParsers().parsingListEventId(json, 'accepted'),
notCreated: JsonParsers().parsingListId(json, 'notCreated'),
);
}

@override
List<Object?> get props => [...super.props, accepted, notCreated];
}
42 changes: 42 additions & 0 deletions lib/util/json_parsers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'package:jmap_dart_client/http/converter/account_id_converter.dart';
import 'package:jmap_dart_client/http/converter/calendar/event_id_nullable_converter.dart';
import 'package:jmap_dart_client/http/converter/id_converter.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';

class JsonParsers {
const JsonParsers._();
factory JsonParsers() => _instance;
static const JsonParsers _instance = JsonParsers._();

AccountId parsingAccountId(Map<String, dynamic> json) {
return const AccountIdConverter().fromJson(json['accountId'] as String);
}

List<Id>? parsingListId(Map<String, dynamic> json, String key) {
final jsonListIds = json[key];

if (jsonListIds == null) return null;

if (jsonListIds.runtimeType != List<String>) return null;

return (jsonListIds as List<String>)
.map((value) => const IdConverter().fromJson(value))
.toList();
}

List<EventId>? parsingListEventId(Map<String, dynamic> json, String key) {
final jsonListIds = json[key];

if (jsonListIds == null) return null;

if (jsonListIds.runtimeType != List<String>) return null;

return (jsonListIds as List<String>)
.map((value) => const EventIdNullableConverter().fromJson(value))
.where((element) => element != null)
.cast<EventId>()
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import 'package:dio/dio.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http_mock_adapter/http_mock_adapter.dart';
import 'package:jmap_dart_client/http/http_client.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/method/request/calendar_event_reply_method.dart';
import 'package:jmap_dart_client/jmap/core/method/response/calendar_event_reply_response.dart';
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_method.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/reply/calendar_event_accept_response.dart';

void main() {
final baseOption = BaseOptions(method: 'POST');
final dio = Dio(baseOption)..options.baseUrl = 'http://domain.com/jmap';
final dioAdapter = DioAdapter(dio: dio);
final dioAdapterHeaders = {"accept": "application/json;jmapVersion=rfc-8621"};
final httpClient = HttpClient(dio);
final processingInvocation = ProcessingInvocation();
final requestBuilder = JmapRequestBuilder(httpClient, processingInvocation);
final accountId = AccountId(Id('123abc'));
final successBlobId = Id('abc123');
final failureBlobId = Id('def456');
final notFoundBlobId = Id('ghi789');
final blobIds = [successBlobId, failureBlobId, notFoundBlobId];
final methodCallId = MethodCallId('c0');

Map<String, dynamic> constructData(CalendarEventReplyMethod method) => {
"using": method.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
method.methodName.value,
{
"accountId": accountId.id.value,
"blobIds": blobIds.map((id) => id.value).toList(),
},
methodCallId.value
]
]
};

Map<String, dynamic> constructResponse(CalendarEventReplyMethod method) => {
"sessionState": "abcdefghij",
"methodResponses": [[
method.methodName.value,
{
"accountId": accountId.id.value,
"accepted": [successBlobId.value],
"notCreated": [failureBlobId.value],
"notFound": [notFoundBlobId.value],
},
methodCallId.value
]]
};

group('calendar event accept method', () {
final method = CalendarEventAcceptMethod(accountId, blobIds: blobIds);

test('should succeed with success blob data, '
'and fail with failure blob data '
'and not found with not found blob data', () async {
// arrange
final invocation = requestBuilder.invocation(method, methodCallId: methodCallId);
dioAdapter.onPost(
'',
(server) => server.reply(200, constructResponse(method)),
data: constructData(method),
headers: dioAdapterHeaders,
);

// act
final response = (await (requestBuilder..usings(method.requiredCapabilities))
.build()
.execute())
.parse<CalendarEventReplyResponse>(
invocation.methodCallId,
CalendarEventAcceptResponse.deserialize);

// assert
expect((response as CalendarEventAcceptResponse?)?.accepted, equals([EventId(successBlobId.value)]));
expect(response?.notCreated, equals([failureBlobId]));
expect(response?.notFound, equals([notFoundBlobId]));
});
});
}
118 changes: 118 additions & 0 deletions test/util/json_parsers_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/calendar/properties/event_id.dart';
import 'package:jmap_dart_client/util/json_parsers.dart';

void main() {
final jsonParsers = JsonParsers();

group('json parsers test:', () {
group('parse account id test:', () {
test('should return account id when json contains account id',() {
// arrange
const rawAccountId = 'abc123';
final json = {'accountId': rawAccountId};

// act
final accountId = jsonParsers.parsingAccountId(json);

// assert
expect(accountId, AccountId(Id(rawAccountId)));
});

test('should throw TypeError exception when json doesn\'t contains account id',() {
// arrange
final json = <String, dynamic>{};

// assert
expect(
() => jsonParsers.parsingAccountId(json),
throwsA(isA<TypeError>()));
});

test('should throw TypeError exception when accountId json is not String',() {
// arrange
const rawAccountId = 'abc123';
final json = {'accountId': [rawAccountId]};

// assert
expect(
() => jsonParsers.parsingAccountId(json),
throwsA(isA<TypeError>()));
});
});

group('parse list id test:', () {
test('should return list id when json contains list id',() {
// arrange
const rawListId = ['abc123'];
final json = {'listId': rawListId};

// act
final listId = jsonParsers.parsingListId(json, 'listId');

// assert
expect(listId, rawListId.map((id) => Id(id)).toList());
});

test('should return null when json doesn\'t contains list id',() {
// arrange
final json = <String, dynamic>{};

// act
final listId = jsonParsers.parsingListId(json, 'listId');

// assert
expect(listId, null);
});

test('should return null when list id json is not List<String>',() {
// arrange
final json = {'listId': 'abc123'};

// act
final listId = jsonParsers.parsingListId(json, 'listId');

// assert
expect(listId, null);
});
});

group('parse list event id test:', () {
test('should return list event id when json contains list event id',() {
// arrange
const rawListEventId = ['abc123'];
final json = {'listEventId': rawListEventId};

// act
final listEventId = jsonParsers.parsingListEventId(json, 'listEventId');

// assert
expect(listEventId, rawListEventId.map((id) => EventId(id)).toList());
});

test('should return null when json doesn\'t contains list event id',() {
// arrange
final json = <String, dynamic>{};

// act
final listEventId = jsonParsers.parsingListEventId(json, 'listEventId');

// assert
expect(listEventId, null);
});

test('should return null when list event id json is not List<String>',() {
// arrange
final json = {'listEventId': 'abc123'};

// act
final listEventId = jsonParsers.parsingListEventId(json, 'listEventId');

// assert
expect(listEventId, null);
});
});
});
}

0 comments on commit f737823

Please sign in to comment.