TF-3578 Calendar event show free busy status
This commit is contained in:
@@ -0,0 +1,277 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jmap_dart_client/http/http_client.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:model/extensions/account_id_extensions.dart';
|
||||
import 'package:tmail_ui_user/features/email/data/network/calendar_event_api.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/exceptions/calendar_event_exceptions.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/blob_calendar_event.dart';
|
||||
|
||||
import '../../../../fixtures/account_fixtures.dart';
|
||||
import 'calendar_event_api_test.mocks.dart';
|
||||
|
||||
@GenerateNiceMocks([MockSpec<HttpClient>()])
|
||||
void main() {
|
||||
group('CalendarEventAPI::test', () {
|
||||
late HttpClient httpClient;
|
||||
late CalendarEventAPI calendarEventAPI;
|
||||
|
||||
setUp(() {
|
||||
httpClient = MockHttpClient();
|
||||
calendarEventAPI = CalendarEventAPI(httpClient);
|
||||
});
|
||||
|
||||
group('parse::test', () {
|
||||
test('SHOULD return list of BlobCalendarEvent WHEN parse method success', () async {
|
||||
final blobIds = {Id('blob_1'), Id('blob_2')};
|
||||
|
||||
when(httpClient.post(
|
||||
'',
|
||||
data: anyNamed('data'),
|
||||
cancelToken: anyNamed('cancelToken'),
|
||||
)).thenAnswer((_) async => {
|
||||
"sessionState": "2c9f1b12-b35a-43e6-9af2-0106fb53a943",
|
||||
"methodResponses": [
|
||||
[
|
||||
"CalendarEvent/parse",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"parsed": {
|
||||
"blob_1": [
|
||||
{
|
||||
"uid": "event1",
|
||||
"title": "Meeting 1",
|
||||
"start": "2024-03-20T10:00:00Z",
|
||||
"duration": "PT1H"
|
||||
}
|
||||
],
|
||||
"blob_2": [
|
||||
{
|
||||
"uid": "event2",
|
||||
"title": "Meeting 2",
|
||||
"start": "2024-03-21T14:00:00Z",
|
||||
"duration": "PT2H"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"c0"
|
||||
],
|
||||
[
|
||||
"CalendarEventAttendance/get",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"list": [
|
||||
{
|
||||
"blobId": "blob_1",
|
||||
"isFree": true
|
||||
},
|
||||
{
|
||||
"blobId": "blob_2",
|
||||
"isFree": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"c1"
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
final result = await calendarEventAPI.parse(
|
||||
AccountFixtures.aliceAccountId,
|
||||
blobIds
|
||||
);
|
||||
|
||||
verify(httpClient.post(
|
||||
'',
|
||||
data: {
|
||||
"using": [
|
||||
"urn:ietf:params:jmap:core",
|
||||
"com:linagora:params:calendar:event",
|
||||
],
|
||||
"methodCalls": [
|
||||
[
|
||||
"CalendarEvent/parse",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"blobIds": ["blob_1", "blob_2"]
|
||||
},
|
||||
"c0"
|
||||
],
|
||||
[
|
||||
"CalendarEventAttendance/get",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"blobIds": ["blob_1", "blob_2"]
|
||||
},
|
||||
"c1"
|
||||
]
|
||||
]
|
||||
},
|
||||
cancelToken: anyNamed('cancelToken'),
|
||||
)).called(1);
|
||||
|
||||
expect(result, isA<List<BlobCalendarEvent>>());
|
||||
expect(result.length, 2);
|
||||
expect(result[0].blobId.value, 'blob_1');
|
||||
expect(result[0].isFree, true);
|
||||
expect(result[1].blobId.value, 'blob_2');
|
||||
expect(result[1].isFree, false);
|
||||
});
|
||||
|
||||
test('SHOULD throw NotParsableCalendarEventException WHEN response has notParsable', () async {
|
||||
final blobIds = {Id('blob_1')};
|
||||
|
||||
when(httpClient.post(
|
||||
'',
|
||||
data: anyNamed('data'),
|
||||
cancelToken: anyNamed('cancelToken'),
|
||||
)).thenAnswer((_) async => {
|
||||
"sessionState": "2c9f1b12-b35a-43e6-9af2-0106fb53a943",
|
||||
"methodResponses": [
|
||||
[
|
||||
"CalendarEvent/parse",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"notParsable": ["blob_1"]
|
||||
},
|
||||
"c0"
|
||||
],
|
||||
[
|
||||
"CalendarEventAttendance/get",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"list": []
|
||||
},
|
||||
"c1"
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
expect(
|
||||
() => calendarEventAPI.parse(AccountFixtures.aliceAccountId, blobIds),
|
||||
throwsA(isA<NotParsableCalendarEventException>())
|
||||
);
|
||||
});
|
||||
|
||||
test('SHOULD throw NotFoundCalendarEventException WHEN response has notFound', () async {
|
||||
final blobIds = {Id('blob_1')};
|
||||
|
||||
when(httpClient.post(
|
||||
'',
|
||||
data: anyNamed('data'),
|
||||
cancelToken: anyNamed('cancelToken'),
|
||||
)).thenAnswer((_) async => {
|
||||
"sessionState": "2c9f1b12-b35a-43e6-9af2-0106fb53a943",
|
||||
"methodResponses": [
|
||||
[
|
||||
"CalendarEvent/parse",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"notFound": ["blob_1"]
|
||||
},
|
||||
"c0"
|
||||
],
|
||||
[
|
||||
"CalendarEventAttendance/get",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"list": []
|
||||
},
|
||||
"c1"
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
expect(
|
||||
() => calendarEventAPI.parse(AccountFixtures.aliceAccountId, blobIds),
|
||||
throwsA(isA<NotFoundCalendarEventException>())
|
||||
);
|
||||
});
|
||||
|
||||
test('SHOULD throw NotParsableCalendarEventException WHEN response is empty', () async {
|
||||
final blobIds = {Id('blob_1')};
|
||||
|
||||
when(httpClient.post(
|
||||
'',
|
||||
data: anyNamed('data'),
|
||||
cancelToken: anyNamed('cancelToken'),
|
||||
)).thenAnswer((_) async => {
|
||||
"sessionState": "2c9f1b12-b35a-43e6-9af2-0106fb53a943",
|
||||
"methodResponses": [
|
||||
[
|
||||
"CalendarEvent/parse",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString
|
||||
},
|
||||
"c0"
|
||||
],
|
||||
[
|
||||
"CalendarEventAttendance/get",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"list": []
|
||||
},
|
||||
"c1"
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
expect(
|
||||
() => calendarEventAPI.parse(AccountFixtures.aliceAccountId, blobIds),
|
||||
throwsA(isA<NotParsableCalendarEventException>())
|
||||
);
|
||||
});
|
||||
|
||||
test('SHOULD return calendar events with default isFree value WHEN CalendarEventAttendance/get returns error', () async {
|
||||
final blobIds = {Id('blob_1')};
|
||||
|
||||
when(httpClient.post(
|
||||
'',
|
||||
data: anyNamed('data'),
|
||||
cancelToken: anyNamed('cancelToken'),
|
||||
)).thenAnswer((_) async => {
|
||||
"sessionState": "2c9f1b12-b35a-43e6-9af2-0106fb53a943",
|
||||
"methodResponses": [
|
||||
[
|
||||
"CalendarEvent/parse",
|
||||
{
|
||||
"accountId": AccountFixtures.aliceAccountId.asString,
|
||||
"parsed": {
|
||||
"blob_1": [
|
||||
{
|
||||
"uid": "event1",
|
||||
"title": "Meeting 1",
|
||||
"start": "2024-03-20T10:00:00Z",
|
||||
"duration": "PT1H"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"c0"
|
||||
],
|
||||
[
|
||||
"error",
|
||||
{
|
||||
"type": "invalidArguments",
|
||||
"description": "Invalid blobIds"
|
||||
},
|
||||
"c1"
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
final result = await calendarEventAPI.parse(
|
||||
AccountFixtures.aliceAccountId,
|
||||
blobIds
|
||||
);
|
||||
|
||||
expect(result, isA<List<BlobCalendarEvent>>());
|
||||
expect(result.length, 1);
|
||||
expect(result[0].blobId.value, 'blob_1');
|
||||
expect(result[0].isFree, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/widgets/calendar_event/event_time_information_widget.dart';
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
|
||||
import '../../../../../fixtures/widget_fixtures.dart';
|
||||
|
||||
void main() {
|
||||
setUp(() {
|
||||
Get.put<ResponsiveUtils>(ResponsiveUtils());
|
||||
Get.put<ImagePaths>(ImagePaths());
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
Get.reset();
|
||||
});
|
||||
|
||||
group('EventTimeInformationWidget tests', () {
|
||||
Widget makeTestableWidget({
|
||||
required String timeEvent,
|
||||
required bool isFree,
|
||||
}) {
|
||||
return WidgetFixtures.makeTestableWidget(
|
||||
child: EventTimeInformationWidget(
|
||||
timeEvent: timeEvent,
|
||||
isFree: isFree,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('should show error icon with tooltip when isFree is false', (tester) async {
|
||||
// arrange
|
||||
final widget = makeTestableWidget(
|
||||
timeEvent: '10:00 AM - 11:00 AM',
|
||||
isFree: false,
|
||||
);
|
||||
|
||||
// act
|
||||
await tester.pumpWidget(widget);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// assert
|
||||
final svgFinder = find.byWidgetPredicate((widget) {
|
||||
return widget is SvgPicture
|
||||
&& (widget.bytesLoader as SvgAssetLoader).assetName == Get.find<ImagePaths>().icError;
|
||||
});
|
||||
expect(svgFinder, findsOneWidget);
|
||||
expect(find.byType(Tooltip), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('should not show error icon when isFree is true', (tester) async {
|
||||
// arrange
|
||||
final widget = makeTestableWidget(
|
||||
timeEvent: '10:00 AM - 11:00 AM',
|
||||
isFree: true,
|
||||
);
|
||||
|
||||
// act
|
||||
await tester.pumpWidget(widget);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// assert
|
||||
expect(find.byType(SvgPicture), findsNothing);
|
||||
expect(find.byType(Tooltip), findsNothing);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user