fix: 修正双击点赞与心形联动

This commit is contained in:
Zhou Weidong committed 2026-10-22 22:30:01 +08:00
1 parent 78d0166eb7
commit 68ccfa21c0
8 files changed
+200 -64

No files matched your search

+142
View File
@@ -0,0 +1,142 @@
// Author: fruit.com.cn
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/core/data/services/interaction_controller.dart';
import 'package:fruitshorts/core/theme/app_theme.dart';
import 'package:fruitshorts/l10n/app_localizations.dart';
import 'package:fruitshorts/pages/player/widgets/home_feed_overlay.dart';
import '../support/fake_catalog.dart';
import '../support/fake_haptics.dart';
import '../support/fake_interaction_repositories.dart';
void main() {
testWidgets('quick double tap likes without pausing', (tester) async {
final repository = FakeInteractionRepository();
final haptics = FakeHaptics();
final key = GlobalKey<_HarnessState>();
await _pumpHarness(tester, repository, haptics, key);
final gesture = find.byKey(const Key('home-feed-gesture'));
final center = tester.getCenter(gesture);
await tester.tapAt(center);
await tester.pump(const Duration(milliseconds: 100));
await tester.tapAt(center);
await tester.pumpAndSettle();
expect(key.currentState!.pauseToggles, 0);
expect(repository.likeTargets, hasLength(1));
expect(haptics.lightImpacts, 1);
expect(
find.descendant(
of: find.byKey(const Key('rail-like')),
matching: find.byIcon(Icons.favorite_rounded),
),
findsOneWidget,
);
});
testWidgets('single tap toggles playback after 280ms', (tester) async {
final key = GlobalKey<_HarnessState>();
await _pumpHarness(tester, FakeInteractionRepository(), FakeHaptics(), key);
await tester.tapAt(
tester.getCenter(find.byKey(const Key('home-feed-gesture'))),
);
await tester.pump(const Duration(milliseconds: 279));
expect(key.currentState!.pauseToggles, 0);
await tester.pump(const Duration(milliseconds: 2));
expect(key.currentState!.pauseToggles, 1);
});
}
Future<void> _pumpHarness(
WidgetTester tester,
FakeInteractionRepository repository,
FakeHaptics haptics,
GlobalKey<_HarnessState> key,
) async {
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.dark(),
locale: const Locale('en'),
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: _Harness(key: key, repository: repository, haptics: haptics),
),
);
await tester.pumpAndSettle();
}
class _Harness extends StatefulWidget {
const _Harness({super.key, required this.repository, required this.haptics});
final FakeInteractionRepository repository;
final FakeHaptics haptics;
@override
State<_Harness> createState() => _HarnessState();
}
class _HarnessState extends State<_Harness> {
late final InteractionController interactions = InteractionController(
widget.repository,
);
int pauseToggles = 0;
Future<void> _like({bool likeOnly = false}) async {
await widget.haptics.lightImpact();
final episodeId = demoDramas.first.episodes.first.id;
if (interactions.isEpisodeBusy(episodeId) ||
(likeOnly && interactions.isEpisodeLiked(episodeId))) {
return;
}
await interactions.toggleEpisodeLike(episodeId);
}
@override
void dispose() {
interactions.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
backgroundColor: Colors.black,
body: ListenableBuilder(
listenable: interactions,
builder: (context, _) {
final episode = demoDramas.first.episodes.first;
return HomeFeedOverlay(
l10n: l10n,
drama: demoDramas.first,
episode: episode,
controller: null,
locked: false,
liked: interactions.isEpisodeLiked(episode.id),
likeCount: interactions.episodeLikeCount(episode.id),
saved: false,
visible: true,
boosting: false,
onLike: () => _like(),
onDoubleTapLike: (_) => _like(likeOnly: true),
onSave: () {},
onComments: () {},
onShare: () {},
onDetail: () {},
onOpenFullPlayer: () {},
onTogglePlay: () => setState(() => pauseToggles++),
onBoostStart: () {},
onBoostEnd: () {},
onMore: () {},
);
},
),
);
}
}