feat(flutter): 接入互动评论点赞举报
This commit is contained in:
1 parent
45f5f25640
commit
d361034226
39 files changed
+3298
-462
No files matched your search
@@ -0,0 +1,192 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fruitshorts/core/data/models/comment.dart';
|
||||
import 'package:fruitshorts/core/data/models/interaction.dart';
|
||||
import 'package:fruitshorts/core/data/remote/api_client.dart';
|
||||
import 'package:fruitshorts/core/data/services/comment_controller.dart';
|
||||
|
||||
import '../support/fake_interaction_repositories.dart';
|
||||
|
||||
void main() {
|
||||
CommentController controller(
|
||||
FakeCommentRepository comments, {
|
||||
FakeInteractionRepository? interactions,
|
||||
}) => CommentController(
|
||||
comments: comments,
|
||||
interactions: interactions ?? FakeInteractionRepository(),
|
||||
dramaId: '5',
|
||||
);
|
||||
|
||||
test('should_append_next_page_with_cursor_when_has_more_is_true', () async {
|
||||
final repository = FakeCommentRepository(
|
||||
pages: [
|
||||
CommentPage(
|
||||
comments: [commentFixture(id: '2')],
|
||||
nextCursor: '2',
|
||||
hasMore: true,
|
||||
),
|
||||
CommentPage(comments: [commentFixture(id: '1')]),
|
||||
],
|
||||
);
|
||||
final model = controller(repository);
|
||||
|
||||
await model.load();
|
||||
await model.loadMore();
|
||||
|
||||
expect(model.comments.map((item) => item.id), ['2', '1']);
|
||||
expect(model.hasMore, isFalse);
|
||||
expect(repository.pageCalls[0].cursor, isNull);
|
||||
expect(repository.pageCalls[1].cursor, '2');
|
||||
expect(repository.pageCalls.every((call) => call.size == 20), isTrue);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('should_use_server_content_and_pending_status_when_review_is_returned', () async {
|
||||
final repository = FakeCommentRepository(
|
||||
publishResult: commentFixture(
|
||||
id: '3',
|
||||
content: 'replaced ***',
|
||||
status: 'pending',
|
||||
mine: true,
|
||||
),
|
||||
);
|
||||
final model = controller(repository);
|
||||
|
||||
final result = await model.publish(' replaced badword ');
|
||||
|
||||
expect(result.isSuccess, isTrue);
|
||||
expect(repository.publishCalls.single.content, 'replaced badword');
|
||||
expect(model.comments.single.content, 'replaced ***');
|
||||
expect(model.comments.single.isPending, isTrue);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('should_expose_backend_message_and_keep_existing_list_when_publish_is_blocked', () async {
|
||||
final repository = FakeCommentRepository(
|
||||
publishError: const ApiException(400, '评论包含敏感词'),
|
||||
);
|
||||
final model = controller(repository);
|
||||
await model.load();
|
||||
|
||||
final result = await model.publish('blocked');
|
||||
|
||||
expect(result.isSuccess, isFalse);
|
||||
expect(result.errorMessage, '评论包含敏感词');
|
||||
expect(model.comments, isEmpty);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('should_insert_reply_under_root_and_request_replies_with_root_id', () async {
|
||||
final root = commentFixture(id: '10', replyCount: 1);
|
||||
final reply = commentFixture(
|
||||
id: '11',
|
||||
parentId: '10',
|
||||
rootId: '10',
|
||||
content: 'Reply',
|
||||
mine: true,
|
||||
);
|
||||
final repository = FakeCommentRepository(
|
||||
pages: [
|
||||
CommentPage(comments: [root]),
|
||||
CommentPage(comments: [reply]),
|
||||
],
|
||||
publishResult: reply,
|
||||
);
|
||||
final model = controller(repository);
|
||||
await model.load();
|
||||
|
||||
await model.loadReplies('10');
|
||||
final result = await model.publish('Reply', replyTo: root);
|
||||
|
||||
expect(result.isSuccess, isTrue);
|
||||
expect(repository.publishCalls.single.parentId, '10');
|
||||
expect(repository.pageCalls.last.rootId, '10');
|
||||
expect(model.repliesFor('10').map((item) => item.id), ['11']);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('should_restore_comment_at_original_position_when_delete_fails', () async {
|
||||
final first = commentFixture(id: '2', mine: true);
|
||||
final second = commentFixture(id: '1');
|
||||
final repository = FakeCommentRepository(
|
||||
pages: [
|
||||
CommentPage(comments: [first, second]),
|
||||
],
|
||||
deleteError: const ApiException(500, '删除失败'),
|
||||
);
|
||||
final model = controller(repository);
|
||||
await model.load();
|
||||
|
||||
final result = await model.delete(first);
|
||||
|
||||
expect(result.isSuccess, isFalse);
|
||||
expect(result.errorMessage, '删除失败');
|
||||
expect(model.comments.map((item) => item.id), ['2', '1']);
|
||||
expect(repository.deleteCalls, ['2']);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('should_remove_own_comment_when_delete_succeeds', () async {
|
||||
final own = commentFixture(id: '2', mine: true);
|
||||
final repository = FakeCommentRepository(
|
||||
pages: [
|
||||
CommentPage(comments: [own]),
|
||||
],
|
||||
);
|
||||
final model = controller(repository);
|
||||
await model.load();
|
||||
|
||||
final result = await model.delete(own);
|
||||
|
||||
expect(result.isSuccess, isTrue);
|
||||
expect(model.comments, isEmpty);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('should_optimistically_update_comment_like_and_apply_server_count', () async {
|
||||
final comment = commentFixture(id: '2', likeCount: 3, liked: false);
|
||||
final interactions = FakeInteractionRepository(
|
||||
nextLikeResult: const LikeToggleResult(liked: true, count: 8),
|
||||
);
|
||||
final repository = FakeCommentRepository(
|
||||
pages: [
|
||||
CommentPage(comments: [comment]),
|
||||
],
|
||||
);
|
||||
final model = controller(repository, interactions: interactions);
|
||||
await model.load();
|
||||
|
||||
final pending = model.toggleLike(comment);
|
||||
expect(model.comments.single.liked, isTrue);
|
||||
expect(model.comments.single.likeCount, 4);
|
||||
final result = await pending;
|
||||
|
||||
expect(result.isSuccess, isTrue);
|
||||
expect(model.comments.single.liked, isTrue);
|
||||
expect(model.comments.single.likeCount, 8);
|
||||
expect(interactions.likeTargets, ['COMMENT:2']);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('should_rollback_comment_like_when_request_fails', () async {
|
||||
final comment = commentFixture(id: '2', likeCount: 3, liked: true);
|
||||
final interactions = FakeInteractionRepository()
|
||||
..likeError = const ApiException(500, '点赞失败');
|
||||
final repository = FakeCommentRepository(
|
||||
pages: [
|
||||
CommentPage(comments: [comment]),
|
||||
],
|
||||
);
|
||||
final model = controller(repository, interactions: interactions);
|
||||
await model.load();
|
||||
|
||||
final result = await model.toggleLike(comment);
|
||||
|
||||
expect(result.isSuccess, isFalse);
|
||||
expect(result.errorMessage, '点赞失败');
|
||||
expect(model.comments.single.liked, isTrue);
|
||||
expect(model.comments.single.likeCount, 3);
|
||||
model.dispose();
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user