import 'dart:typed_data'; import 'package:file_selector/file_selector.dart' as fs; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:image/image.dart' as img; import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart'; import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart'; import 'package:pdf_signature/ui/features/pdf/view_model/pdf_export_view_model.dart'; import 'package:pdf_signature/data/repositories/document_repository.dart'; import 'package:pdf_signature/data/repositories/signature_asset_repository.dart'; import 'package:pdf_signature/data/repositories/signature_card_repository.dart'; import 'package:pdf_signature/domain/models/signature_asset.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; // preferences_providers.dart no longer exports pageViewModeProvider Future pumpWithOpenPdf(WidgetTester tester) async { await tester.pumpWidget( ProviderScope( overrides: [ documentRepositoryProvider.overrideWith( (ref) => DocumentStateNotifier()..openSample(), ), pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: true), ), pdfExportViewModelProvider.overrideWith( (ref) => PdfExportViewModel(ref), ), ], child: MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: PdfSignatureHomePage( onPickPdf: () async {}, onClosePdf: () {}, currentFile: fs.XFile(''), ), ), ), ); await tester.pump(); } Future pumpWithOpenPdfAndSig(WidgetTester tester) async { // Create a tiny sample signature image (PNG) for deterministic tests final canvas = img.Image(width: 60, height: 30); // White background img.fill(canvas, color: img.ColorUint8.rgb(255, 255, 255)); // Black rectangle line as a "signature" img.drawLine( canvas, x1: 5, y1: 15, x2: 55, y2: 15, color: img.ColorUint8.rgb(0, 0, 0), ); final bytes = img.encodePng(canvas); // Create minimal PDF bytes for testing (this is a very basic PDF structure) // This is just enough to make the PDF viewer work in tests final pdfBytes = Uint8List.fromList([ 0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x34, 0x0A, // %PDF-1.4 0x31, 0x20, 0x30, 0x20, 0x6F, 0x62, 0x6A, 0x0A, // 1 0 obj 0x3C, 0x3C, 0x2F, 0x54, 0x79, 0x70, 0x65, 0x20, 0x2F, 0x43, 0x61, 0x74, 0x61, 0x6C, 0x6F, 0x67, 0x20, 0x2F, 0x50, 0x61, 0x67, 0x65, 0x73, 0x20, 0x32, 0x20, 0x30, 0x20, 0x52, 0x3E, 0x3E, 0x0A, 0x65, 0x6E, 0x64, 0x6F, 0x62, 0x6A, 0x0A, 0x32, 0x20, 0x30, 0x20, 0x6F, 0x62, 0x6A, 0x0A, 0x3C, 0x3C, 0x2F, 0x54, 0x79, 0x70, 0x65, 0x20, 0x2F, 0x50, 0x61, 0x67, 0x65, 0x73, 0x20, 0x2F, 0x43, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x31, 0x20, 0x2F, 0x4B, 0x69, 0x64, 0x73, 0x20, 0x5B, 0x33, 0x20, 0x30, 0x20, 0x52, 0x5D, 0x3E, 0x3E, 0x0A, 0x65, 0x6E, 0x64, 0x6F, 0x62, 0x6A, 0x0A, 0x33, 0x20, 0x30, 0x20, 0x6F, 0x62, 0x6A, 0x0A, 0x3C, 0x3C, 0x2F, 0x54, 0x79, 0x70, 0x65, 0x20, 0x2F, 0x50, 0x61, 0x67, 0x65, 0x20, 0x2F, 0x50, 0x61, 0x72, 0x65, 0x6E, 0x74, 0x20, 0x32, 0x20, 0x30, 0x20, 0x52, 0x20, 0x2F, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x42, 0x6F, 0x78, 0x20, 0x5B, 0x30, 0x20, 0x30, 0x20, 0x36, 0x31, 0x32, 0x20, 0x37, 0x39, 0x32, 0x5D, 0x20, 0x2F, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x73, 0x20, 0x34, 0x20, 0x30, 0x20, 0x52, 0x3E, 0x3E, 0x0A, 0x65, 0x6E, 0x64, 0x6F, 0x62, 0x6A, 0x0A, 0x34, 0x20, 0x30, 0x20, 0x6F, 0x62, 0x6A, 0x0A, 0x3C, 0x3C, 0x2F, 0x4C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x34, 0x34, 0x3E, 0x3E, 0x0A, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6D, 0x0A, 0x42, 0x54, 0x0A, // BT 0x2F, 0x46, 0x31, 0x20, 0x32, 0x34, 0x20, 0x54, 0x66, 0x0A, // /F1 24 Tf 0x31, 0x30, 0x30, 0x20, 0x37, 0x30, 0x30, 0x20, 0x54, 0x64, 0x0A, // 100 700 Td 0x28, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, 0x44, 0x46, 0x29, 0x20, 0x54, 0x6A, 0x0A, // (Test PDF) Tj 0x45, 0x54, 0x0A, // ET 0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6D, 0x0A, 0x65, 0x6E, 0x64, 0x6F, 0x62, 0x6A, 0x0A, 0x78, 0x72, 0x65, 0x66, 0x0A, 0x30, 0x20, 0x35, 0x0A, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x6E, 0x20, 0x0A, 0x30, 0x30, 0x30, 0x30, 0x31, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x6E, 0x20, 0x0A, 0x30, 0x30, 0x30, 0x30, 0x32, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x6E, 0x20, 0x0A, 0x30, 0x30, 0x30, 0x30, 0x33, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x6E, 0x20, 0x0A, 0x30, 0x30, 0x30, 0x30, 0x34, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x6E, 0x20, 0x0A, 0x74, 0x72, 0x61, 0x69, 0x6C, 0x65, 0x72, 0x0A, 0x3C, 0x3C, 0x2F, 0x53, 0x69, 0x7A, 0x65, 0x20, 0x35, 0x20, 0x2F, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x31, 0x20, 0x30, 0x20, 0x52, 0x3E, 0x3E, 0x0A, 0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66, 0x0A, 0x35, 0x35, 0x39, 0x0A, 0x25, 0x25, 0x45, 0x4F, 0x46, 0x0A, // %%EOF ]); // keep drawing for determinism even if bytes unused in simplified UI await tester.pumpWidget( ProviderScope( overrides: [ documentRepositoryProvider.overrideWith((ref) { final notifier = DocumentStateNotifier()..openSample(); // Set PDF bytes so the viewer can display something notifier.state = notifier.state.copyWith(pickedPdfBytes: pdfBytes); // Add a signature placement on page 1 notifier.addPlacement( page: 1, rect: const Rect.fromLTWH(0.1, 0.1, 0.3, 0.2), asset: SignatureAsset( sigImage: img.decodeImage(Uint8List.fromList(bytes))!, ), ); return notifier; }), signatureAssetRepositoryProvider.overrideWith((ref) { final repo = SignatureAssetRepository(); final image = img.decodeImage(Uint8List.fromList(bytes))!; repo.addImage(image, name: 'test'); return repo; }), signatureCardRepositoryProvider.overrideWith((ref) { final cardRepo = SignatureCardStateNotifier(); final asset = SignatureAsset( sigImage: img.decodeImage(Uint8List.fromList(bytes))!, name: 'test', ); cardRepo.addWithAsset(asset, 0.0); return cardRepo; }), // In new model, interactive overlay not implemented; keep library empty pdfViewModelProvider.overrideWith( (ref) => PdfViewModel(ref, useMockViewer: true), ), pdfExportViewModelProvider.overrideWith( (ref) => PdfExportViewModel(ref), ), ], child: MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: PdfSignatureHomePage( onPickPdf: () async {}, onClosePdf: () {}, currentFile: fs.XFile(''), ), ), ), ); await tester.pump(); }