129 lines
4.7 KiB
Dart
129 lines
4.7 KiB
Dart
// 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<void>();
|
|
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();
|
|
});
|
|
}
|