Files
social-app/apps/test/features/calendar/data/calendar_api_test.dart
T

139 lines
4.5 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:social_app/core/api/mock_api_client.dart';
import 'package:social_app/features/calendar/data/calendar_api.dart';
import 'package:social_app/features/calendar/data/models/schedule_item_model.dart';
void main() {
group('CalendarApi', () {
test('listByRange parses metadata and attachments', () async {
final client = MockApiClient();
client.registerPatternHandler(
RegExp(r'^/api/v1/schedule-items\?.*$'),
'GET',
(_) => [
{
'id': 'evt_1',
'title': '晨会',
'description': '同步',
'start_at': '2026-03-11T01:00:00Z',
'end_at': '2026-03-11T02:00:00Z',
'timezone': 'Asia/Shanghai',
'metadata': {
'color': '#4F46E5',
'location': '会议室A',
'notes': '带电脑',
'reminder_minutes': 15,
'attachments': [
{
'name': '议程文档',
'visible_to': ['u1'],
'url': 'https://example.com/a',
'note': '会前阅读',
'content': null,
'type': 'document',
},
],
'version': 1,
'new_field': 'future',
},
'status': 'active',
'source_type': 'manual',
'created_at': '2026-03-10T01:00:00Z',
'updated_at': '2026-03-10T01:30:00Z',
},
],
);
final api = CalendarApi(client);
final result = await api.listByRange(
startAt: DateTime.utc(2026, 3, 1),
endAt: DateTime.utc(2026, 3, 31, 23, 59, 59),
);
expect(result, hasLength(1));
expect(result.first.metadata?.attachments, hasLength(1));
expect(result.first.metadata?.raw['new_field'], 'future');
expect(result.first.metadata?.reminderMinutes, 15);
expect(result.first.startAt.isUtc, isFalse);
});
test('create serializes full metadata', () async {
final client = MockApiClient();
client.registerHandler('/api/v1/schedule-items', 'POST', (request) {
final body = request.data as Map<String, dynamic>;
expect(body['metadata']['version'], 1);
expect(body['metadata']['reminder_minutes'], 15);
expect(body['metadata']['attachments'], isA<List<dynamic>>());
return {
'id': 'evt_2',
...body,
'status': 'active',
'source_type': 'manual',
'created_at': '2026-03-10T01:00:00Z',
'updated_at': '2026-03-10T01:00:00Z',
};
});
final api = CalendarApi(client);
final created = await api.create(
ScheduleItemModel(
id: 'evt_local',
title: '评审',
startAt: DateTime.utc(2026, 3, 11, 3),
endAt: DateTime.utc(2026, 3, 11, 4),
metadata: ScheduleMetadata(
color: '#F59E0B',
location: '线上',
notes: '准备 demo',
attachments: [Attachment(name: 'PRD', type: 'document')],
reminderMinutes: 15,
version: 1,
),
),
);
expect(created.id, 'evt_2');
expect(created.metadata?.location, '线上');
});
test('update does not send unknown metadata fields', () async {
final client = MockApiClient();
client.registerHandler('/api/v1/schedule-items/evt_3', 'PATCH', (
request,
) {
final body = request.data as Map<String, dynamic>;
final metadata = body['metadata'] as Map<String, dynamic>;
expect(metadata.containsKey('new_field'), isFalse);
expect(metadata['reminder_minutes'], 30);
return {
'id': 'evt_3',
...body,
'status': 'active',
'source_type': 'manual',
'created_at': '2026-03-10T01:00:00Z',
'updated_at': '2026-03-11T01:00:00Z',
};
});
final api = CalendarApi(client);
final event = ScheduleItemModel(
id: 'evt_3',
title: '同步会',
startAt: DateTime.utc(2026, 3, 11, 1),
metadata: ScheduleMetadata.fromJson({
'color': '#3B82F6',
'location': '会议室B',
'notes': '更新周报',
'attachments': const [],
'version': 1,
'reminder_minutes': 30,
'new_field': 'future',
}),
);
final updated = await api.update(event);
expect(updated.id, 'evt_3');
});
});
}