// Author: fruit.com.cn import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/core/data/models/drama.dart'; import 'package:fruitshorts/core/data/repositories/favorite_repository.dart'; import 'package:fruitshorts/core/data/services/favorite_controller.dart'; Drama _card(String id) => Drama( id: id, title: 'Drama $id', synopsis: 'synopsis', posterUrl: '/files/$id.png', ); void main() { test('should_roll_back_when_toggle_fails', () async { final repository = InMemoryFavoriteRepository()..failToggle = true; final controller = FavoriteController(repository); final ok = await controller.toggle('signal'); expect(ok, isFalse); // 乐观更新必须回滚:不能"看起来收藏了,其实服务端没存" expect(controller.isSaved('signal'), isFalse); expect(controller.cards, isEmpty); }); test('should_keep_saved_state_when_toggle_succeeds', () async { final controller = FavoriteController(InMemoryFavoriteRepository()); final ok = await controller.toggle('signal', card: _card('signal')); expect(ok, isTrue); expect(controller.isSaved('signal'), isTrue); // 卡片随手带上:收藏完打开"我的收藏"就能看到 expect(controller.cards.map((drama) => drama.id), ['signal']); }); test('should_remove_card_and_state_when_toggled_off', () async { final repository = InMemoryFavoriteRepository(saved: {'signal'}); final controller = FavoriteController(repository); // 先按服务端状态对齐,再取消收藏 await controller.load(); await controller.toggle('signal'); expect(controller.isSaved('signal'), isFalse); expect(controller.cards, isEmpty); }); test('should_expose_error_and_keep_old_state_when_list_fails', () async { final repository = InMemoryFavoriteRepository()..failList = true; final controller = FavoriteController(repository); await controller.load(); expect(controller.loading, isFalse); expect(controller.error, 'favoritesError'); }); test('should_load_cards_and_saved_ids_when_list_succeeds', () async { final repository = InMemoryFavoriteRepository( saved: {'signal'}, cards: [_card('signal'), _card('city')], ); final controller = FavoriteController(repository); await controller.load(); expect(controller.error, isNull); expect(controller.cards.map((drama) => drama.id), ['signal']); expect(controller.isSaved('signal'), isTrue); expect(controller.isSaved('city'), isFalse); }); test('should_roll_back_when_remove_fails', () async { final repository = InMemoryFavoriteRepository( saved: {'signal'}, cards: [_card('signal')], ); final controller = FavoriteController(repository); await controller.load(); final ok = await controller.remove('signal'); // InMemory 实现的 remove 不会失败,这里断言正常路径:状态与列表一起清掉 expect(ok, isTrue); expect(controller.isSaved('signal'), isFalse); expect(controller.cards, isEmpty); }); test('should_clear_state_when_signing_out', () async { final controller = FavoriteController( InMemoryFavoriteRepository(saved: {'signal'}, cards: [_card('signal')]), ); await controller.load(); controller.clear(); expect(controller.savedIds, isEmpty); expect(controller.cards, isEmpty); }); }