TF-3752 Add more test case for SetForwardMethod unit test

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-05-27 03:27:05 +07:00
committed by Dat H. Pham
parent b0d3467770
commit 34cc7abe9b
@@ -4,11 +4,18 @@ import 'package:forward/forward/forward_id.dart';
import 'package:forward/forward/get/get_forward_method.dart';
import 'package:forward/forward/get/get_forward_response.dart';
import 'package:forward/forward/set/set_forward_method.dart';
import 'package:forward/forward/set/set_forward_response.dart';
import 'package:forward/forward/tmail_forward.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/capability/capability_identifier.dart';
import 'package:jmap_dart_client/jmap/core/error/method/error_method_response.dart';
import 'package:jmap_dart_client/jmap/core/error/method/exception/error_method_response_exception.dart';
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart';
import 'package:jmap_dart_client/jmap/core/state.dart';
import 'package:jmap_dart_client/jmap/jmap_request.dart';
void main() {
@@ -135,4 +142,792 @@ void main() {
expect(getForwardResponse.list, containsAll({expectedUpdated}));
});
});
group('set forward method test:', () {
const String baseUrl = 'http://domain.com/jmap';
late final Dio dio;
late final DioAdapter dioAdapter;
final methodCallId = MethodCallId('c0');
final bobAccountId = AccountId(Id('bob'));
final sessionState = State('sessionState');
final newState = State('newState');
final tmailForward = TMailForward(
id: ForwardIdSingleton.forwardIdSingleton,
localCopy: true,
forwards: {'targetA@domain.org', 'targetB@domain.org'},
);
setUpAll(() {
dio = Dio(BaseOptions(method: 'POST'))..options.baseUrl = baseUrl;
dioAdapter = DioAdapter(dio: dio);
});
test('Should fail when wrong account id', () async {
// Arrange
final unknownAccountId = AccountId(Id('unknownAccountId'));
final setForwardMethod = SetForwardMethod(unknownAccountId)
..addUpdatesSingleton({
tmailForward.id!.id : tmailForward
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"error",
{
"type": "accountNotFound",
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": unknownAccountId.id.value,
"update": {tmailForward.id!.id.value: tmailForward.toJson()}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
// Assert
expect(
() => responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
),
throwsA(ErrorMethodResponseException(AccountNotFoundMethodResponse())),
);
});
test('Should return unknown method when missing one capability', () async {
// Arrange
final listCapabilitiesUsed = {CapabilityIdentifier.jmapCore};
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({
tmailForward.id!.id : tmailForward
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"error",
{
"type": "unknownMethod",
"description":
"Missing capability(ies): com:linagora:params:jmap:forward"
},
methodCallId.value,
],
],
},
),
data: {
"using": listCapabilitiesUsed
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {tmailForward.id!.id.value: tmailForward.toJson()}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(listCapabilitiesUsed))
.build()
.execute();
// Assert
expect(
() => responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
),
throwsA(ErrorMethodResponseException(UnknownMethodResponse(
description:
'Missing capability(ies): com:linagora:params:jmap:forward',
))),
);
});
test('Should return unknown method when missing all capabilities',
() async {
// Arrange
final listCapabilitiesUsed = <CapabilityIdentifier>{};
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({
tmailForward.id!.id : tmailForward
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"error",
{
"type": "unknownMethod",
"description":
"Missing capability(ies): urn:ietf:params:jmap:core, com:linagora:params:jmap:forward"
},
methodCallId.value,
],
],
},
),
data: {
"using": listCapabilitiesUsed
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {tmailForward.id!.id.value: tmailForward.toJson()}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(listCapabilitiesUsed))
.build()
.execute();
// Assert
expect(
() => responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
),
throwsA(ErrorMethodResponseException(UnknownMethodResponse(
description:
'Missing capability(ies): urn:ietf:params:jmap:core, com:linagora:params:jmap:forward',
))),
);
});
test('Should return success', () async {
// Arrange
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({
tmailForward.id!.id : tmailForward
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"Forward/set",
{
"accountId": bobAccountId.id.value,
"newState": newState.value,
"updated": {tmailForward.id!.id.value: {}}
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {tmailForward.id!.id.value: tmailForward.toJson()}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
final setForwardResponse = responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
);
// Assert
expect(
setForwardResponse?.updated,
isNotEmpty,
);
expect(
setForwardResponse?.notUpdated,
isNull,
);
expect(
setForwardResponse?.notCreated,
isNull,
);
expect(
setForwardResponse?.notDestroyed,
isNull,
);
});
test('Should fail when missing forwards', () async {
// Arrange
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({
tmailForward.id!.id : TMailForward(
localCopy: true,
)
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"Forward/set",
{
"accountId": bobAccountId.id.value,
"newState": newState.value,
"notUpdated": {
tmailForward.id!.id.value: {
"type": "invalidArguments",
"description": "Missing '/forwards' property"
}
}
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {
tmailForward.id!.id.value: {"localCopy": true}
}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
final setForwardResponse = responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
);
// Assert
expect(
setForwardResponse?.updated,
isNull,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.type,
SetError.invalidArguments,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.description,
'Missing \'/forwards\' property',
);
});
test('Should fail when missing localCopy', () async {
// Arrange
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({
tmailForward.id!.id : TMailForward(
forwards: {},
)
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"Forward/set",
{
"accountId": bobAccountId.id.value,
"newState": newState.value,
"notUpdated": {
tmailForward.id!.id.value: {
"type": "invalidArguments",
"description": "Missing '/localCopy' property"
}
}
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {
tmailForward.id!.id.value: {"forwards": []}
}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
final setForwardResponse = responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
);
// Assert
expect(
setForwardResponse?.updated,
isNull,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.type,
SetError.invalidArguments,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.description,
'Missing \'/localCopy\' property',
);
});
test('Should fail when invalid key', () async {
// Arrange
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({
Id('invalidKey'): tmailForward
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"Forward/set",
{
"accountId": bobAccountId.id.value,
"newState": newState.value,
"notUpdated": {
"invalidKey": {
"type": "invalidArguments",
"description": "id invalidKey must be singleton"
}
}
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {
"invalidKey": tmailForward.toJson(),
}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
final setForwardResponse = responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
);
// Assert
expect(
setForwardResponse?.updated,
isNull,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.type,
SetError.invalidArguments,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.description,
'id invalidKey must be singleton',
);
});
test('Should fail when invalid forwards', () async {
// Arrange
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({
tmailForward.id!.id: tmailForward.copyWith(
forwards: {"123\$#%\$#invalid"}
)
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"Forward/set",
{
"accountId": bobAccountId.id.value,
"newState": newState.value,
"notUpdated": {
tmailForward.id!.id.value: {
"type": "invalidArguments",
"description":
"'/forwards(0)' property is not valid: Invalid mailAddress: Out of data at position 1 in '123\$\$#%\$\$#invalid'"
}
}
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {
tmailForward.id!.id.value: tmailForward.copyWith(
forwards: {"123\$#%\$#invalid"}
).toJson(),
}
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
final setForwardResponse = responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
);
// Assert
expect(
setForwardResponse?.updated,
isNull,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.type,
SetError.invalidArguments,
);
expect(
setForwardResponse?.notUpdated?.values.firstOrNull?.description,
'\'/forwards(0)\' property is not valid: Invalid mailAddress: Out of data at position 1 in \'123\$\$#%\$\$#invalid\'',
);
});
test('Should noop when empty map', () async {
// Arrange
final setForwardMethod = SetForwardMethod(bobAccountId)
..addUpdatesSingleton({});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"Forward/set",
{
"accountId": bobAccountId.id.value,
"newState": newState.value
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": bobAccountId.id.value,
"update": {},
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
final setForwardResponse = responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
);
// Assert
expect(
setForwardResponse?.updated,
isNull,
);
expect(
setForwardResponse?.notUpdated,
isNull,
);
});
test('Should reject from delegated account', () async {
// Arrange
final aliceAccountId = AccountId(Id('Alice'));
final setForwardMethod = SetForwardMethod(aliceAccountId)
..addUpdatesSingleton({
tmailForward.id!.id: tmailForward,
});
final requestBuilder = JmapRequestBuilder(
HttpClient(dio),
ProcessingInvocation(),
);
final invocation = requestBuilder.invocation(
setForwardMethod,
methodCallId: methodCallId,
);
dioAdapter.onPost(
'',
(server) => server.reply(
200,
{
"sessionState": sessionState.value,
"methodResponses": [
[
"error",
{
"type": "forbidden",
"description":
"Access to other accounts settings is forbidden"
},
methodCallId.value,
],
],
},
),
data: {
"using": setForwardMethod.requiredCapabilities
.map((capability) => capability.value.toString())
.toList(),
"methodCalls": [
[
setForwardMethod.methodName.value,
{
"accountId": aliceAccountId.id.value,
"update": {
tmailForward.id!.id.value: tmailForward.toJson(),
},
},
methodCallId.value,
]
]
},
);
// Act
final responseObject = await (requestBuilder
..usings(setForwardMethod.requiredCapabilities))
.build()
.execute();
// Assert
expect(
() => responseObject.parse<SetForwardResponse>(
invocation.methodCallId,
SetForwardResponse.deserialize,
),
throwsA(ErrorMethodResponseException(ForbiddenMethodResponse(
description: 'Access to other accounts settings is forbidden'))),
);
});
});
}