Files
reelbox/tool/download_ui_capture_test.dart

163 lines
6.5 KiB
Dart

// Explicit host-rendered component evidence, not Android-device verification.
import 'dart:io';
import 'dart:ui' as ui;
import 'package:background_downloader/background_downloader.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:reelbox/data/models.dart';
import 'package:reelbox/media/download_button.dart';
import 'package:reelbox/media/download_service.dart';
import 'package:reelbox/media/downloads_page.dart';
import 'package:reelbox/state/app_state.dart';
import '../test/catalog_widget_test.dart' show CatalogApi, mountCatalog;
void main() {
testWidgets('download components at 390px in English and Persian', (
tester,
) async {
await tester.runAsync(() async {
final font = await File('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf')
.readAsBytes();
for (final family in ['Roboto', 'Ahem']) {
await (FontLoader(
family,
)..addFont(Future.value(font.buffer.asByteData()))).load();
}
final icons = await File(
'/root/developer-tools/flutter/bin/cache/artifacts/material_fonts/MaterialIcons-Regular.otf',
).readAsBytes();
await (FontLoader(
'MaterialIcons',
)..addFont(Future.value(icons.buffer.asByteData()))).load();
});
tester.view.physicalSize = const Size(390, 844);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final state = await mountCatalog(tester, CatalogApi(), const Scaffold());
addTearDown(state.dispose);
final boundaryKey = GlobalKey();
final paused = DownloadEntry.fromTask(
DownloadTask(url: 'https://media.example/movie.mp4'),
taskStatus: TaskStatus.paused,
progress: .25,
totalBytes: 104857600,
);
final failed = DownloadEntry.fromTask(
DownloadTask(url: 'https://media.example/expired.mp4'),
taskStatus: TaskStatus.failed,
error: 'HTTP 403: this media URL has expired.',
);
for (final locale in ['en', 'fa']) {
await state.updateSettings(state.prefs.copyWith(locale: locale));
await tester.pumpWidget(
AppScope(
state: state,
child: MaterialApp(
theme: ThemeData.dark(useMaterial3: true).copyWith(
appBarTheme: const AppBarTheme(
titleTextStyle: TextStyle(fontFamily: 'Roboto', fontSize: 20),
),
),
home: RepaintBoundary(
key: boundaryKey,
child: Directionality(
textDirection: locale == 'fa'
? TextDirection.rtl
: TextDirection.ltr,
child: Builder(
builder: (context) => Scaffold(
appBar: AppBar(
title: Text(tr(context, 'Downloads', 'دانلودها')),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
Text(
tr(context, 'Source · 720p', 'منبع · 720p'),
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
DownloadButton(
title: const TitleRecord(
id: 7,
title: 'Fixture movie',
),
source: const MediaSource(
quality: '720p',
url: 'https://media.example/movie.mp4',
),
enqueue: ({
required title,
required source,
episode,
}) async {},
),
const SizedBox(height: 18),
for (final entry in [paused, failed])
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
tr(
context,
'Fixture movie · 720p',
'فیلم نمونه · 720p',
),
style: Theme.of(context)
.textTheme
.titleMedium,
),
const SizedBox(height: 12),
DownloadTransferDetails(entry: entry),
const SizedBox(height: 8),
DownloadControls(
entry: entry,
onPause: () async {},
onResume: () async {},
onRetry: () async {},
onCancel: () async {},
),
],
),
),
),
],
),
),
),
),
),
),
),
);
await tester.pumpAndSettle();
expect(find.byType(DownloadButton), findsOneWidget);
expect(find.byType(DownloadTransferDetails), findsNWidgets(2));
expect(tester.takeException(), isNull);
final boundary =
boundaryKey.currentContext!.findRenderObject()!
as RenderRepaintBoundary;
await tester.runAsync(() async {
final directory = Directory(
'/root/reelbox/build/download-ui-verification',
);
await directory.create(recursive: true);
final image = await boundary.toImage(pixelRatio: 2);
final bytes = await image.toByteData(format: ui.ImageByteFormat.png);
await File('${directory.path}/downloads-$locale.png')
.writeAsBytes(bytes!.buffer.asUint8List());
image.dispose();
});
}
await tester.pumpWidget(const SizedBox());
});
}