2026-09-21 17:20:43 +08:00
|
|
|
|
/// 分享二维码对话框 widget 测试(UI-01 §4.5 分层重构)。
|
2026-09-19 01:56:38 +08:00
|
|
|
|
///
|
2026-09-21 17:20:43 +08:00
|
|
|
|
/// 覆盖:分层结构(相册标题 → 白底二维码 → URL 文本 → 复制为主/浏览器
|
|
|
|
|
|
/// 打开为次)、QrImageView 以 viewer URL({VIEWER_BASE}/a/{token})渲染、
|
|
|
|
|
|
/// 复制按钮写入剪贴板并提示、「在浏览器中打开」经注入的替身启动器
|
|
|
|
|
|
/// 打开 URL 并关闭对话框。
|
2026-09-19 01:56:38 +08:00
|
|
|
|
library;
|
|
|
|
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
import 'package:flutter/services.dart';
|
2026-09-21 17:20:43 +08:00
|
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
2026-09-19 01:56:38 +08:00
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
|
|
import 'package:photo_live/core/config.dart';
|
|
|
|
|
|
import 'package:photo_live/l10n/app_localizations.dart';
|
|
|
|
|
|
import 'package:photo_live/pages/share_qr_dialog.dart';
|
|
|
|
|
|
import 'package:qr_flutter/qr_flutter.dart';
|
|
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
|
const token = 'sharetoken000000000001';
|
|
|
|
|
|
|
2026-09-21 17:20:43 +08:00
|
|
|
|
Future<void> pumpDialog(
|
|
|
|
|
|
WidgetTester tester, {
|
|
|
|
|
|
String? albumTitle,
|
|
|
|
|
|
UrlLauncher? launcher,
|
|
|
|
|
|
}) async {
|
2026-09-19 01:56:38 +08:00
|
|
|
|
await tester.pumpWidget(
|
2026-09-21 17:20:43 +08:00
|
|
|
|
ProviderScope(
|
|
|
|
|
|
overrides: [
|
|
|
|
|
|
if (launcher != null)
|
|
|
|
|
|
urlLauncherProvider.overrideWith((ref) => launcher),
|
|
|
|
|
|
],
|
|
|
|
|
|
child: MaterialApp(
|
|
|
|
|
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
|
|
|
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
|
|
|
|
|
// 复制提示走 ScaffoldMessenger:包一层 Scaffold 供 SnackBar 挂载。
|
|
|
|
|
|
home: Scaffold(
|
|
|
|
|
|
body: Center(
|
|
|
|
|
|
child: ShareQrDialog(
|
|
|
|
|
|
publicToken: token,
|
|
|
|
|
|
albumTitle: albumTitle,
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
2026-09-19 01:56:38 +08:00
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-21 17:20:43 +08:00
|
|
|
|
testWidgets('分层渲染:相册标题 → 二维码(data 为观众链接)→ URL 文本',
|
|
|
|
|
|
(tester) async {
|
|
|
|
|
|
await pumpDialog(tester, albumTitle: 'Opening Gala');
|
2026-09-19 01:56:38 +08:00
|
|
|
|
|
|
|
|
|
|
final url = ApiConfig.viewerAlbumUrl(token);
|
|
|
|
|
|
// qr_flutter 4.1 未公开 QrImageView.data(私有 _data),以同源的
|
|
|
|
|
|
// SelectableText 文本断言 URL 构造(二维码与文本同用该局部变量)。
|
|
|
|
|
|
expect(find.byType(QrImageView), findsOneWidget);
|
|
|
|
|
|
expect(
|
|
|
|
|
|
tester.widget<SelectableText>(find.byType(SelectableText)).data,
|
|
|
|
|
|
url,
|
|
|
|
|
|
);
|
|
|
|
|
|
expect(url, 'http://10.0.2.2:5175/a/$token');
|
2026-09-21 17:20:43 +08:00
|
|
|
|
// 分层:主标题 = 相册名,副标题 = 通用标题,脚注 = 扫码/链接提示。
|
|
|
|
|
|
expect(find.text('Opening Gala'), findsOneWidget);
|
|
|
|
|
|
expect(find.text('Share QR code'), findsOneWidget);
|
2026-09-19 01:56:38 +08:00
|
|
|
|
expect(find.text('Scan the code or open the link to view'), findsOneWidget);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-09-21 17:20:43 +08:00
|
|
|
|
testWidgets('复制按钮(主操作)→ 剪贴板收到 URL + 已复制提示', (tester) async {
|
2026-09-19 01:56:38 +08:00
|
|
|
|
final clipboardCalls = <MethodCall>[];
|
|
|
|
|
|
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
|
|
|
|
|
|
SystemChannels.platform,
|
|
|
|
|
|
(call) async {
|
|
|
|
|
|
clipboardCalls.add(call);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
await pumpDialog(tester);
|
|
|
|
|
|
await tester.tap(find.text('Copy link'));
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
|
|
final url = ApiConfig.viewerAlbumUrl(token);
|
|
|
|
|
|
expect(
|
|
|
|
|
|
clipboardCalls.any(
|
|
|
|
|
|
(c) =>
|
|
|
|
|
|
c.method == 'Clipboard.setData' &&
|
|
|
|
|
|
(c.arguments as Map<String, dynamic>)['text'] == url,
|
|
|
|
|
|
),
|
|
|
|
|
|
isTrue,
|
|
|
|
|
|
);
|
|
|
|
|
|
expect(find.text('Copied'), findsOneWidget);
|
|
|
|
|
|
});
|
2026-09-21 17:20:43 +08:00
|
|
|
|
|
|
|
|
|
|
testWidgets('在浏览器中打开(次操作)→ 启动器收到 URL + 关闭对话框',
|
|
|
|
|
|
(tester) async {
|
|
|
|
|
|
final launchedUrls = <String>[];
|
|
|
|
|
|
await pumpDialog(
|
|
|
|
|
|
tester,
|
|
|
|
|
|
launcher: (url) async {
|
|
|
|
|
|
launchedUrls.add(url);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
await tester.tap(find.text('Open in browser'));
|
|
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
|
|
|
|
|
|
|
|
expect(launchedUrls, [ApiConfig.viewerAlbumUrl(token)]);
|
|
|
|
|
|
expect(find.byType(ShareQrDialog), findsNothing, reason: '打开成功后关闭');
|
|
|
|
|
|
});
|
2026-09-19 01:56:38 +08:00
|
|
|
|
}
|