TF-4169 Add Label/get method
This commit is contained in:
@@ -0,0 +1,41 @@
|
|||||||
|
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/http/converter/properties_converter.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/method/request/get_method.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/request/result_reference.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:labels/labels.dart';
|
||||||
|
|
||||||
|
part 'get_label_method.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(
|
||||||
|
explicitToJson: true,
|
||||||
|
converters: [
|
||||||
|
IdConverter(),
|
||||||
|
AccountIdConverter(),
|
||||||
|
PropertiesConverter(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class GetLabelMethod extends GetMethod {
|
||||||
|
GetLabelMethod(super.accountId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
MethodName get methodName => MethodName('Label/get');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<CapabilityIdentifier> get requiredCapabilities => {
|
||||||
|
CapabilityIdentifier.jmapCore,
|
||||||
|
LabelsConstants.labelsCapability,
|
||||||
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [methodName, accountId, ids, requiredCapabilities];
|
||||||
|
|
||||||
|
factory GetLabelMethod.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$GetLabelMethodFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() => _$GetLabelMethodToJson(this);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
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/http/converter/state_converter.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/core/method/response/get_response.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
import 'package:labels/labels.dart';
|
||||||
|
|
||||||
|
part 'get_label_response.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(
|
||||||
|
converters: [
|
||||||
|
StateConverter(),
|
||||||
|
AccountIdConverter(),
|
||||||
|
IdConverter(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class GetLabelResponse extends GetResponse<Label> {
|
||||||
|
GetLabelResponse(super.accountId, super.state, super.list, super.notFound);
|
||||||
|
|
||||||
|
factory GetLabelResponse.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$GetLabelResponseFromJson(json);
|
||||||
|
|
||||||
|
static GetLabelResponse deserialize(Map<String, dynamic> json) {
|
||||||
|
return GetLabelResponse.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$GetLabelResponseToJson(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [accountId, state, list, notFound];
|
||||||
|
}
|
||||||
+9
-1
@@ -178,7 +178,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.10.1"
|
version: "0.10.1"
|
||||||
dio:
|
dio:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: dio
|
name: dio
|
||||||
sha256: "9fdbf71baeb250fc9da847f6cb2052196f62c19906a3657adfc18631a667d316"
|
sha256: "9fdbf71baeb250fc9da847f6cb2052196f62c19906a3657adfc18631a667d316"
|
||||||
@@ -259,6 +259,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.2"
|
||||||
|
http_mock_adapter:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: http_mock_adapter
|
||||||
|
sha256: "0e7eaa5d77a273af1c2b5ec5066578faaa73039b63ccda5263c200756f24441a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.2"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ dependencies:
|
|||||||
|
|
||||||
json_annotation: 4.8.0
|
json_annotation: 4.8.0
|
||||||
|
|
||||||
|
dio: 5.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
@@ -32,6 +34,8 @@ dev_dependencies:
|
|||||||
|
|
||||||
json_serializable: 6.6.1
|
json_serializable: 6.6.1
|
||||||
|
|
||||||
|
http_mock_adapter: 0.4.2
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
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/jmap_request.dart';
|
||||||
|
import 'package:labels/labels.dart';
|
||||||
|
import 'package:labels/method/get/get_label_method.dart';
|
||||||
|
import 'package:labels/method/get/get_label_response.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('GetLabelMethod – additional test cases', () {
|
||||||
|
final accountId = AccountId(
|
||||||
|
Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6'),
|
||||||
|
);
|
||||||
|
|
||||||
|
Dio createDio() {
|
||||||
|
final dio = Dio(BaseOptions(method: 'POST'))
|
||||||
|
..options.baseUrl = 'http://domain.com/jmap';
|
||||||
|
return dio;
|
||||||
|
}
|
||||||
|
|
||||||
|
JmapRequestBuilder createBuilder(Dio dio) {
|
||||||
|
return JmapRequestBuilder(
|
||||||
|
HttpClient(dio),
|
||||||
|
ProcessingInvocation(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> buildRequestPayload({
|
||||||
|
required List<String> ids,
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
"using": [
|
||||||
|
"urn:ietf:params:jmap:core",
|
||||||
|
"com:linagora:params:jmap:labels"
|
||||||
|
],
|
||||||
|
"methodCalls": [
|
||||||
|
[
|
||||||
|
"Label/get",
|
||||||
|
{
|
||||||
|
"accountId": accountId.id.value,
|
||||||
|
"ids": ids,
|
||||||
|
},
|
||||||
|
"c0"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('should return all labels when none are notFound', () async {
|
||||||
|
// Arrange
|
||||||
|
final dio = createDio();
|
||||||
|
final adapter = DioAdapter(dio: dio);
|
||||||
|
|
||||||
|
final labelA = Label(Id('A'), 'Label A', 'labelA', HexColor('#111111'));
|
||||||
|
final labelB = Label(Id('B'), 'Label B', 'labelB', HexColor('#222222'));
|
||||||
|
|
||||||
|
adapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"sessionState": "state",
|
||||||
|
"methodResponses": [
|
||||||
|
[
|
||||||
|
"Label/get",
|
||||||
|
{
|
||||||
|
"accountId": accountId.id.value,
|
||||||
|
"state": "s1",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"id": "A",
|
||||||
|
"displayName": "Label A",
|
||||||
|
"keyword": "labelA",
|
||||||
|
"color": "#111111",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "B",
|
||||||
|
"displayName": "Label B",
|
||||||
|
"keyword": "labelB",
|
||||||
|
"color": "#222222",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"notFound": []
|
||||||
|
},
|
||||||
|
"c0"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
data: buildRequestPayload(ids: ['A', 'B']),
|
||||||
|
);
|
||||||
|
|
||||||
|
final builder = createBuilder(dio);
|
||||||
|
final method = GetLabelMethod(accountId)..addIds({Id('A'), Id('B')});
|
||||||
|
final invocation = builder.invocation(method);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final response = await (builder..usings(method.requiredCapabilities))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final parsed = response.parse<GetLabelResponse>(
|
||||||
|
invocation.methodCallId,
|
||||||
|
GetLabelResponse.deserialize,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(parsed!.list, containsAll({labelA, labelB}));
|
||||||
|
expect(parsed.notFound, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return notFound only when no labels exist', () async {
|
||||||
|
// Arrange
|
||||||
|
final dio = createDio();
|
||||||
|
final adapter = DioAdapter(dio: dio);
|
||||||
|
|
||||||
|
adapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"sessionState": "state",
|
||||||
|
"methodResponses": [
|
||||||
|
[
|
||||||
|
"Label/get",
|
||||||
|
{
|
||||||
|
"accountId": accountId.id.value,
|
||||||
|
"state": "s1",
|
||||||
|
"list": [],
|
||||||
|
"notFound": ["X1", "X2"]
|
||||||
|
},
|
||||||
|
"c0"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
data: buildRequestPayload(ids: ['X1', 'X2']),
|
||||||
|
);
|
||||||
|
|
||||||
|
final builder = createBuilder(dio);
|
||||||
|
final method = GetLabelMethod(accountId)..addIds({Id('X1'), Id('X2')});
|
||||||
|
final invocation = builder.invocation(method);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final response = await (builder..usings(method.requiredCapabilities))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final parsed = response.parse<GetLabelResponse>(
|
||||||
|
invocation.methodCallId,
|
||||||
|
GetLabelResponse.deserialize,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(parsed!.list, isEmpty);
|
||||||
|
expect(parsed.notFound, containsAll({Id('X1'), Id('X2')}));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return empty results when server returns empty list',
|
||||||
|
() async {
|
||||||
|
// Arrange
|
||||||
|
final dio = createDio();
|
||||||
|
final adapter = DioAdapter(dio: dio);
|
||||||
|
|
||||||
|
adapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"sessionState": "state",
|
||||||
|
"methodResponses": [
|
||||||
|
[
|
||||||
|
"Label/get",
|
||||||
|
{
|
||||||
|
"accountId": accountId.id.value,
|
||||||
|
"state": "s1",
|
||||||
|
"list": [],
|
||||||
|
"notFound": []
|
||||||
|
},
|
||||||
|
"c0"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
data: buildRequestPayload(ids: ['A']),
|
||||||
|
);
|
||||||
|
|
||||||
|
final builder = createBuilder(dio);
|
||||||
|
final method = GetLabelMethod(accountId)..addIds({Id('A')});
|
||||||
|
final invocation = builder.invocation(method);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final response = await (builder..usings(method.requiredCapabilities))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final parsed = response.parse<GetLabelResponse>(
|
||||||
|
invocation.methodCallId,
|
||||||
|
GetLabelResponse.deserialize,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(parsed!.list, isEmpty);
|
||||||
|
expect(parsed.notFound, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should throw DioException when server returns 500', () async {
|
||||||
|
// Arrange
|
||||||
|
final dio = createDio();
|
||||||
|
final adapter = DioAdapter(dio: dio);
|
||||||
|
|
||||||
|
adapter.onPost(
|
||||||
|
'',
|
||||||
|
(server) => server.reply(500, {}),
|
||||||
|
data: buildRequestPayload(ids: ['A']),
|
||||||
|
);
|
||||||
|
|
||||||
|
final builder = createBuilder(dio);
|
||||||
|
final method = GetLabelMethod(accountId)..addIds({Id('A')});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
final future =
|
||||||
|
(builder..usings(method.requiredCapabilities)).build().execute();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(future, throwsA(isA<DioError>()));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user