Skip to content

Commit ad42ac8

Browse files
committed
TF-3372 Support Reference Destroy to reduce JMAP requests
1 parent bb4ffba commit ad42ac8

File tree

3 files changed

+172
-2
lines changed

3 files changed

+172
-2
lines changed

lib/jmap/core/method/request/set_method.dart

+13-2
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
22
import 'package:jmap_dart_client/jmap/core/id.dart';
33
import 'package:jmap_dart_client/jmap/core/method/method.dart';
44
import 'package:jmap_dart_client/jmap/core/patch_object.dart';
5+
import 'package:jmap_dart_client/jmap/core/request/result_reference.dart';
56
import 'package:jmap_dart_client/jmap/core/state.dart';
67
import 'package:json_annotation/json_annotation.dart';
78

89
abstract class SetMethod<T> extends MethodRequiringAccountId
9-
with OptionalIfInState, OptionalCreate<T>, OptionalDestroy, OptionalUpdate {
10+
with OptionalIfInState, OptionalCreate<T>, OptionalDestroy, OptionalUpdate,
11+
OptionalReferenceDestroy {
1012
SetMethod(AccountId accountId) : super(accountId);
1113
}
1214

1315
abstract class SetMethodNoNeedAccountId<T> extends Method
14-
with OptionalCreate<T>, OptionalDestroy, OptionalUpdate {
16+
with OptionalCreate<T>, OptionalDestroy, OptionalUpdate, OptionalReferenceDestroy {
1517
SetMethodNoNeedAccountId() : super();
1618
}
1719

@@ -78,3 +80,12 @@ mixin OptionalUpdateSingleton<T> {
7880
updateSingleton?.addAll(updates);
7981
}
8082
}
83+
84+
mixin OptionalReferenceDestroy {
85+
@JsonKey(name: '#destroy', includeIfNull: false)
86+
ResultReference? referenceDestroy;
87+
88+
void addReferenceDestroy(ResultReference resultReferenceDestroy) {
89+
referenceDestroy = resultReferenceDestroy;
90+
}
91+
}

lib/jmap/mail/email/set/set_email_method.dart

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class SetEmailMethod extends SetMethod<Email> {
4141
writeNotNull('destroy', destroy
4242
?.map((destroyId) => const IdConverter()
4343
.toJson(destroyId)).toList());
44+
writeNotNull('#destroy', referenceDestroy?.toJson());
4445

4546
return val;
4647
}
+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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/capability/capability_identifier.dart';
7+
import 'package:jmap_dart_client/jmap/core/id.dart';
8+
import 'package:jmap_dart_client/jmap/core/request/reference_path.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/email/email_comparator.dart';
12+
import 'package:jmap_dart_client/jmap/mail/email/email_comparator_property.dart';
13+
import 'package:jmap_dart_client/jmap/mail/email/email_filter_condition.dart';
14+
import 'package:jmap_dart_client/jmap/mail/email/query/query_email_method.dart';
15+
import 'package:jmap_dart_client/jmap/mail/email/query/query_email_response.dart';
16+
import 'package:jmap_dart_client/jmap/mail/email/set/set_email_method.dart';
17+
import 'package:jmap_dart_client/jmap/mail/email/set/set_email_response.dart';
18+
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
19+
20+
void main() {
21+
group('empty trash folder', () {
22+
test('base on Email/query + Email/set', () async {
23+
final baseOption = BaseOptions(method: 'POST');
24+
final dio = Dio(baseOption)
25+
..options.baseUrl = 'http://domain.com/jmap';
26+
final dioAdapter = DioAdapter(dio: dio);
27+
dioAdapter.onPost(
28+
'',
29+
(server) => server.reply(200, {
30+
'sessionState': '2c9f1b12-b35a-43e6-9af2-0106fb53a943',
31+
'methodResponses': [
32+
[
33+
'Email/query',
34+
{
35+
'accountId': '871ae8d53c475bffcd0530c2c673a18862a6ab967b1ac1f78c581fd150eb4120',
36+
'queryState': '9b4f0a48',
37+
'canCalculateChanges': false,
38+
'ids': [
39+
'c141aff0-a665-11ef-8719-49ce43e9b8e8',
40+
'3b4d65e0-a58b-11ef-8719-49ce43e9b8e8',
41+
'c927f050-a0b4-11ef-b19d-250264ebca76',
42+
'97794bf0-a0ad-11ef-b19d-250264ebca76',
43+
'7fa6d100-a0ad-11ef-b19d-250264ebca76',
44+
'1729c0c0-9b61-11ef-bb9d-71e3f2afce5e',
45+
'cf039960-9b60-11ef-bb9d-71e3f2afce5e',
46+
'87531730-9b60-11ef-bb9d-71e3f2afce5e'
47+
],
48+
'position': 0,
49+
'limit': 256
50+
},
51+
'c0'
52+
],
53+
[
54+
'Email/set',
55+
{
56+
'accountId': '871ae8d53c475bffcd0530c2c673a18862a6ab967b1ac1f78c581fd150eb4120',
57+
'oldState': 'a1f36a90-c3a1-11ef-8bac-4d07695fed6f',
58+
'newState': 'a1f36a90-c3a1-11ef-8bac-4d07695fed6f',
59+
'destroyed': [
60+
'c141aff0-a665-11ef-8719-49ce43e9b8e8',
61+
'3b4d65e0-a58b-11ef-8719-49ce43e9b8e8',
62+
'c927f050-a0b4-11ef-b19d-250264ebca76',
63+
'97794bf0-a0ad-11ef-b19d-250264ebca76',
64+
'7fa6d100-a0ad-11ef-b19d-250264ebca76',
65+
'1729c0c0-9b61-11ef-bb9d-71e3f2afce5e',
66+
'cf039960-9b60-11ef-bb9d-71e3f2afce5e',
67+
'87531730-9b60-11ef-bb9d-71e3f2afce5e'
68+
]
69+
},
70+
'c1'
71+
]
72+
]
73+
}),
74+
data: {
75+
"methodCalls": [
76+
[
77+
"Email/query",
78+
{
79+
"accountId": "871ae8d53c475bffcd0530c2c673a18862a6ab967b1ac1f78c581fd150eb4120",
80+
"filter": {
81+
"inMailbox": "025b0580-6422-11ef-a702-5d10e1ebf1c3"
82+
},
83+
"sort": [
84+
{
85+
"isAscending": false,
86+
"property": "receivedAt"
87+
}
88+
]
89+
},
90+
"c0"
91+
],
92+
[
93+
"Email/set",
94+
{
95+
"accountId": "871ae8d53c475bffcd0530c2c673a18862a6ab967b1ac1f78c581fd150eb4120",
96+
"#destroy": {
97+
"resultOf": "c0",
98+
"name": "Email/query",
99+
"path": "/ids/*"
100+
}
101+
},
102+
"c1"
103+
]
104+
],
105+
"using": [
106+
"urn:ietf:params:jmap:core",
107+
"urn:ietf:params:jmap:mail"
108+
],
109+
},
110+
headers: {
111+
"accept": "application/json;jmapVersion=rfc-8621",
112+
"content-length": 813,
113+
}
114+
);
115+
116+
final httpClient = HttpClient(dio);
117+
final processingInvocation = ProcessingInvocation();
118+
final jmapRequestBuilder = JmapRequestBuilder(httpClient, processingInvocation);
119+
final accountId = AccountId(Id('871ae8d53c475bffcd0530c2c673a18862a6ab967b1ac1f78c581fd150eb4120'));
120+
121+
final queryEmailMethod = QueryEmailMethod(accountId)
122+
..addSorts({EmailComparator(EmailComparatorProperty.receivedAt)..setIsAscending(false)})
123+
..addFilters(EmailFilterCondition(inMailbox: MailboxId((Id('025b0580-6422-11ef-a702-5d10e1ebf1c3')))));
124+
final queryEmailInvocation = jmapRequestBuilder.invocation(queryEmailMethod, methodCallId: MethodCallId('c0'));
125+
126+
final setEmailMethod = SetEmailMethod(accountId)
127+
..addReferenceDestroy(
128+
processingInvocation.createResultReference(
129+
queryEmailInvocation.methodCallId,
130+
ReferencePath.idsPath,
131+
)
132+
);
133+
final setEmailInvocation = jmapRequestBuilder.invocation(
134+
setEmailMethod,
135+
methodCallId: MethodCallId('c1')
136+
);
137+
138+
final result = await (jmapRequestBuilder
139+
..usings({CapabilityIdentifier.jmapCore, CapabilityIdentifier.jmapMail}))
140+
.build()
141+
.execute();
142+
143+
final resulQuery = result.parse<QueryEmailResponse>(
144+
queryEmailInvocation.methodCallId,
145+
QueryEmailResponse.deserialize
146+
);
147+
expect(resulQuery!.canCalculateChanges, isFalse);
148+
expect(resulQuery.ids, hasLength(8));
149+
150+
final resultSet = result.parse<SetEmailResponse>(
151+
setEmailInvocation.methodCallId,
152+
SetEmailResponse.deserialize
153+
);
154+
expect(resultSet!.destroyed, hasLength(8));
155+
expect(resultSet.destroyed, containsAll(resulQuery.ids));
156+
});
157+
});
158+
}

0 commit comments

Comments
 (0)