96 lines
3.0 KiB
Dart
96 lines
3.0 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:fruitshorts/core/data/models/notice.dart';
|
|
import 'package:fruitshorts/core/data/remote/api_client.dart';
|
|
import 'package:fruitshorts/core/data/repositories/notice_repository.dart';
|
|
import 'package:fruitshorts/core/data/services/notices_controller.dart';
|
|
|
|
void main() {
|
|
test('should_append_next_page_until_loaded_count_reaches_total', () async {
|
|
final repository = ScriptedNoticeRepository([
|
|
NoticePage(total: 3, notices: [_notice('1'), _notice('2')]),
|
|
NoticePage(total: 3, notices: [_notice('3')]),
|
|
]);
|
|
final controller = NoticesController(repository);
|
|
|
|
await controller.load();
|
|
expect(controller.notices.map((item) => item.id), ['1', '2']);
|
|
expect(controller.hasMore, isTrue);
|
|
|
|
await controller.loadMore();
|
|
expect(controller.notices.map((item) => item.id), ['1', '2', '3']);
|
|
expect(controller.hasMore, isFalse);
|
|
expect(repository.calls.map((call) => call.pageIndex), [1, 2]);
|
|
});
|
|
|
|
test('should_show_empty_state_when_total_is_zero', () async {
|
|
final controller = NoticesController(
|
|
ScriptedNoticeRepository([const NoticePage(total: 0)]),
|
|
);
|
|
|
|
await controller.load();
|
|
|
|
expect(controller.loading, isFalse);
|
|
expect(controller.notices, isEmpty);
|
|
expect(controller.hasMore, isFalse);
|
|
expect(controller.error, isNull);
|
|
});
|
|
|
|
test('should_preserve_backend_message_when_page_load_fails', () async {
|
|
final repository = ScriptedNoticeRepository([])
|
|
..error = const ApiException(500, '公告服务暂不可用');
|
|
final controller = NoticesController(repository);
|
|
|
|
await controller.load();
|
|
|
|
expect(controller.error, '公告服务暂不可用');
|
|
expect(controller.notices, isEmpty);
|
|
});
|
|
|
|
test('should_replace_list_when_refreshed', () async {
|
|
final repository = ScriptedNoticeRepository([
|
|
NoticePage(total: 2, notices: [_notice('1'), _notice('2')]),
|
|
NoticePage(total: 1, notices: [_notice('9')]),
|
|
]);
|
|
final controller = NoticesController(repository);
|
|
await controller.load();
|
|
|
|
await controller.refresh();
|
|
|
|
expect(controller.notices.map((item) => item.id), ['9']);
|
|
expect(controller.hasMore, isFalse);
|
|
});
|
|
}
|
|
|
|
AppNotice _notice(String id) => AppNotice(
|
|
id: id,
|
|
title: 'Notice $id',
|
|
content: 'Content $id',
|
|
type: 'SYSTEM',
|
|
publishAt: DateTime(2026, 10, 17, 12),
|
|
);
|
|
|
|
class ScriptedNoticeRepository implements NoticeRepository {
|
|
ScriptedNoticeRepository(this.pages);
|
|
|
|
final List<NoticePage> pages;
|
|
final List<NoticePageCall> calls = [];
|
|
Object? error;
|
|
|
|
@override
|
|
Future<NoticePage> page({required int pageIndex, int pageSize = 20}) async {
|
|
calls.add(NoticePageCall(pageIndex: pageIndex, pageSize: pageSize));
|
|
if (error != null) throw error!;
|
|
if (pages.isEmpty) return const NoticePage(total: 0);
|
|
return pages.removeAt(0);
|
|
}
|
|
}
|
|
|
|
class NoticePageCall {
|
|
const NoticePageCall({required this.pageIndex, required this.pageSize});
|
|
|
|
final int pageIndex;
|
|
final int pageSize;
|
|
}
|