// Author: fruit.com.cn import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/core/data/models/interaction.dart'; import 'package:fruitshorts/core/data/remote/api_client.dart'; import 'package:fruitshorts/core/data/services/interaction_controller.dart'; import '../support/fake_interaction_repositories.dart'; void main() { test('should_update_drama_like_optimistically_and_use_server_state_when_toggle_succeeds', () async { final repository = FakeInteractionRepository(); final gate = Completer(); repository.likeGate = gate; final controller = InteractionController(repository); final future = controller.toggleDramaLike('5'); expect(controller.isLiked('5'), isTrue); expect(repository.likeTargets, ['DRAMA:5']); repository.nextLikeResult = const LikeToggleResult(liked: false, count: 0); gate.complete(); final result = await future; expect(result.isSuccess, isTrue); expect(controller.isLiked('5'), isFalse); expect(controller.likeCount('5'), 0); controller.dispose(); }); test('should_expose_latest_server_count_when_two_toggles_succeed', () async { final repository = FakeInteractionRepository( nextLikeResult: const LikeToggleResult(liked: true, count: 12), ); final controller = InteractionController(repository); await controller.toggleDramaLike('5'); expect(controller.likeCount('5'), 12); repository.nextLikeResult = const LikeToggleResult(liked: false, count: 11); await controller.toggleDramaLike('5'); expect(controller.likeCount('5'), 11); controller.dispose(); }); test('should_rollback_drama_like_when_toggle_fails', () async { final repository = FakeInteractionRepository( nextLikeResult: const LikeToggleResult(liked: true, count: 3), ); final controller = InteractionController(repository); await controller.toggleDramaLike('5'); repository.likeError = const ApiException(500, '点赞失败'); final result = await controller.toggleDramaLike('5'); expect(result.isSuccess, isFalse); expect(result.errorMessage, '点赞失败'); expect(controller.isLiked('5'), isTrue); controller.dispose(); }); test('should_toggle_episode_like_with_plus_one_and_minus_one', () async { final repository = FakeInteractionRepository( nextLikeResult: const LikeToggleResult(liked: true, count: 8), ); final controller = InteractionController(repository); await controller.toggleEpisodeLike('episode-5'); expect(repository.likeTargets, ['EPISODE:episode-5']); expect(controller.isEpisodeLiked('episode-5'), isTrue); expect(controller.episodeLikeCount('episode-5'), 8); expect(controller.isLiked('episode-5'), isFalse); repository.nextLikeResult = const LikeToggleResult(liked: false, count: 7); await controller.toggleEpisodeLike('episode-5'); expect(controller.isEpisodeLiked('episode-5'), isFalse); expect(controller.episodeLikeCount('episode-5'), 7); controller.dispose(); }); test('should_isolate_episode_like_cache_by_episode_and_drama', () async { final repository = FakeInteractionRepository( nextLikeResult: const LikeToggleResult(liked: true, count: 8), ); final controller = InteractionController(repository); await controller.toggleEpisodeLike('episode-1'); repository.nextLikeResult = const LikeToggleResult(liked: true, count: 3); await controller.toggleEpisodeLike('episode-2'); repository.nextLikeResult = const LikeToggleResult(liked: false, count: 7); await controller.toggleEpisodeLike('episode-1'); repository.nextLikeResult = const LikeToggleResult(liked: true, count: 12); await controller.toggleDramaLike('episode-1'); expect(controller.isEpisodeLiked('episode-1'), isFalse); expect(controller.episodeLikeCount('episode-1'), 7); expect(controller.isEpisodeLiked('episode-2'), isTrue); expect(controller.episodeLikeCount('episode-2'), 3); expect(controller.isLiked('episode-1'), isTrue); expect(controller.likeCount('episode-1'), 12); expect(repository.likeTargets, [ 'EPISODE:episode-1', 'EPISODE:episode-2', 'EPISODE:episode-1', 'DRAMA:episode-1', ]); controller.dispose(); }); test('should_clear_account_scoped_drama_likes_when_session_changes', () async { final repository = FakeInteractionRepository( nextLikeResult: const LikeToggleResult(liked: true, count: 1), ); final controller = InteractionController(repository); await controller.toggleDramaLike('5'); controller.clear(); expect(controller.isLiked('5'), isFalse); expect(controller.likeCount('5'), isNull); controller.dispose(); }); }