From 189bc7e6e657642d3c1234088bce3b68fe2e0baf Mon Sep 17 00:00:00 2001 From: insleker Date: Wed, 10 Sep 2025 22:17:36 +0800 Subject: [PATCH] feat: partially implement integration test --- integration_test/export_flow_test.dart | 34 ++++++++++++++----- .../pdf/widgets/pdf_mock_continuous_list.dart | 8 +++++ .../features/pdf/widgets/pdf_providers.dart | 5 +++ lib/ui/features/pdf/widgets/pdf_screen.dart | 24 ++++++------- .../pdf/widgets/signature_overlay.dart | 2 +- 5 files changed, 49 insertions(+), 24 deletions(-) diff --git a/integration_test/export_flow_test.dart b/integration_test/export_flow_test.dart index e209732..f3b5eaf 100644 --- a/integration_test/export_flow_test.dart +++ b/integration_test/export_flow_test.dart @@ -8,9 +8,12 @@ import 'package:image/image.dart' as img; import 'package:pdf_signature/data/services/export_service.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/data/repositories/document_repository.dart'; import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart'; +import 'package:pdf_signature/ui/features/pdf/widgets/pdf_providers.dart'; +import 'package:pdf_signature/ui/features/pdf/widgets/ui_services.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:pdf_signature/data/repositories/preferences_repository.dart'; import 'package:pdf_signature/l10n/app_localizations.dart'; class RecordingExporter extends ExportService { @@ -29,14 +32,18 @@ void main() { tester, ) async { final fake = RecordingExporter(); + SharedPreferences.setMockInitialValues({}); + final prefs = await SharedPreferences.getInstance(); await tester.pumpWidget( ProviderScope( overrides: [ - documentRepositoryProvider.overrideWith( - (ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'), + preferencesRepositoryProvider.overrideWith( + (ref) => PreferencesStateNotifier(prefs), ), - signatureProvider.overrideWith( - (ref) => SignatureCardStateNotifier()..placeDefaultRect(), + documentRepositoryProvider.overrideWith( + (ref) => + DocumentStateNotifier() + ..openPicked(path: 'test.pdf', pageCount: 5), ), useMockViewerProvider.overrideWith((ref) => true), exportServiceProvider.overrideWith((_) => fake), @@ -82,11 +89,18 @@ void main() { ) async { final sigBytes = _makeSig(); + SharedPreferences.setMockInitialValues({}); + final prefs = await SharedPreferences.getInstance(); await tester.pumpWidget( ProviderScope( overrides: [ + preferencesRepositoryProvider.overrideWith( + (ref) => PreferencesStateNotifier(prefs), + ), documentRepositoryProvider.overrideWith( - (ref) => DocumentStateNotifier()..openPicked(path: 'test.pdf'), + (ref) => + DocumentStateNotifier() + ..openPicked(path: 'test.pdf', pageCount: 5), ), signatureAssetRepositoryProvider.overrideWith((ref) { final c = SignatureAssetRepository(); @@ -119,15 +133,17 @@ void main() { // Programmatically simulate confirm: add placement with current rect and bound image, then clear active overlay. final ctx = tester.element(find.byType(PdfSignatureHomePage)); final container = ProviderScope.containerOf(ctx); - final sigState = container.read(signatureProvider); - final r = sigState.rect!; + final r = container.read(activeRectProvider)!; final lib = container.read(signatureAssetRepositoryProvider); final asset = lib.isNotEmpty ? lib.first : null; final pdf = container.read(documentRepositoryProvider); container .read(documentRepositoryProvider.notifier) .addPlacement(page: pdf.currentPage, rect: r, asset: asset); - container.read(signatureProvider.notifier).clearActiveOverlay(); + // Clear active overlay by hiding signatures temporarily + container.read(signatureVisibilityProvider.notifier).state = false; + await tester.pump(); + container.read(signatureVisibilityProvider.notifier).state = true; await tester.pumpAndSettle(); final placed = find.byKey(const Key('placed_signature_0')); diff --git a/lib/ui/features/pdf/widgets/pdf_mock_continuous_list.dart b/lib/ui/features/pdf/widgets/pdf_mock_continuous_list.dart index 5e06657..3e082f6 100644 --- a/lib/ui/features/pdf/widgets/pdf_mock_continuous_list.dart +++ b/lib/ui/features/pdf/widgets/pdf_mock_continuous_list.dart @@ -138,6 +138,14 @@ class _PdfMockContinuousListState extends ConsumerState { final aspectLocked = ref.watch( aspectLockedProvider, ); + // Publish rect for tests/other UI to observe + WidgetsBinding.instance.addPostFrameCallback(( + _, + ) { + if (!mounted) return; + ref.read(activeRectProvider.notifier).state = + _activeRect; + }); return Stack( children: [ Positioned( diff --git a/lib/ui/features/pdf/widgets/pdf_providers.dart b/lib/ui/features/pdf/widgets/pdf_providers.dart index 9d4e86e..e978068 100644 --- a/lib/ui/features/pdf/widgets/pdf_providers.dart +++ b/lib/ui/features/pdf/widgets/pdf_providers.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; /// Whether to use a mock continuous viewer (ListView) instead of a real PDF viewer. @@ -9,3 +10,7 @@ final signatureVisibilityProvider = StateProvider((ref) => true); /// Whether resizing keeps the current aspect ratio for the active overlay final aspectLockedProvider = StateProvider((ref) => false); + +/// Current active overlay rect (normalized 0..1) for the mock viewer. +/// Integration tests can read this to confirm or compute placements. +final activeRectProvider = StateProvider((ref) => null); diff --git a/lib/ui/features/pdf/widgets/pdf_screen.dart b/lib/ui/features/pdf/widgets/pdf_screen.dart index 68ac870..29eb64d 100644 --- a/lib/ui/features/pdf/widgets/pdf_screen.dart +++ b/lib/ui/features/pdf/widgets/pdf_screen.dart @@ -143,20 +143,16 @@ class _PdfSignatureHomePageState extends ConsumerState { if (path == null || path.trim().isEmpty) return; final fullPath = _ensurePdfExtension(path.trim()); savedPath = fullPath; - if (pdf.pickedPdfBytes != null) { - final out = await exporter.exportSignedPdfFromBytes( - srcBytes: pdf.pickedPdfBytes!, - uiPageSize: _pageSize, - signatureImageBytes: null, - placementsByPage: pdf.placementsByPage, - targetDpi: targetDpi, - ); - if (out != null) { - ok = await exporter.saveBytesToFile( - bytes: out, - outputPath: fullPath, - ); - } + final src = pdf.pickedPdfBytes ?? Uint8List(0); + final out = await exporter.exportSignedPdfFromBytes( + srcBytes: src, + uiPageSize: _pageSize, + signatureImageBytes: null, + placementsByPage: pdf.placementsByPage, + targetDpi: targetDpi, + ); + if (out != null) { + ok = await exporter.saveBytesToFile(bytes: out, outputPath: fullPath); } } if (!kIsWeb) { diff --git a/lib/ui/features/pdf/widgets/signature_overlay.dart b/lib/ui/features/pdf/widgets/signature_overlay.dart index dabd7ed..23db4f0 100644 --- a/lib/ui/features/pdf/widgets/signature_overlay.dart +++ b/lib/ui/features/pdf/widgets/signature_overlay.dart @@ -33,6 +33,7 @@ class SignatureOverlay extends StatelessWidget { width: width, height: height, child: DecoratedBox( + key: Key('placed_signature_$placedIndex'), decoration: BoxDecoration( border: Border.all(color: Colors.red, width: 2), ), @@ -41,7 +42,6 @@ class SignatureOverlay extends StatelessWidget { child: RotatedSignatureImage( bytes: placement.asset.bytes, rotationDeg: placement.rotationDeg, - key: Key('placed_signature_$placedIndex'), ), ), ),