test: resolve error for integration test after upgrade to riverpod3
This commit is contained in:
parent
d6bb64b3bc
commit
473b957587
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cross_file/cross_file.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -8,6 +9,7 @@ import 'package:integration_test/integration_test.dart';
|
|||
import 'package:pdf_signature/data/repositories/document_repository.dart';
|
||||
import 'package:pdf_signature/data/repositories/preferences_repository.dart';
|
||||
import 'package:pdf_signature/data/services/export_service.dart';
|
||||
import 'package:pdf_signature/domain/models/document.dart';
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_export_view_model.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart';
|
||||
|
|
@ -18,6 +20,23 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||
|
||||
// Note: We use the real ExportService via the repository; no mocks here.
|
||||
|
||||
class _PreloadedDocumentStateNotifier extends DocumentStateNotifier {
|
||||
_PreloadedDocumentStateNotifier({
|
||||
required this.bytes,
|
||||
required this.pageCount,
|
||||
ExportService? service,
|
||||
}) : super(service: service);
|
||||
|
||||
final Uint8List bytes;
|
||||
final int pageCount;
|
||||
|
||||
@override
|
||||
Document build() {
|
||||
super.build();
|
||||
return Document(loaded: true, pageCount: pageCount, pickedPdfBytes: bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
|
||||
|
|
@ -34,28 +53,28 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier(service: ExportService())
|
||||
..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
service: ExportService(),
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
// Disable overlays to avoid long-lived overlay animations in CI
|
||||
viewerOverlaysEnabledProvider.overrideWith((ref) => false),
|
||||
pdfExportViewModelProvider.overrideWith(
|
||||
(ref) => PdfExportViewModel(
|
||||
ref,
|
||||
() => PdfExportViewModel(
|
||||
savePathPicker: () async {
|
||||
final dir = Directory.systemTemp.createTempSync('pdfsig_');
|
||||
return '${dir.path}/output.pdf';
|
||||
},
|
||||
savePathPickerWithSuggestedName: (_) async {
|
||||
final dir = Directory.systemTemp.createTempSync('pdfsig_');
|
||||
return '${dir.path}/output.pdf';
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -93,28 +112,30 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier(service: ExportService())
|
||||
..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
service: ExportService(),
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
pdfExportViewModelProvider.overrideWith(
|
||||
(ref) => PdfExportViewModel(
|
||||
ref,
|
||||
() => PdfExportViewModel(
|
||||
savePathPicker: () async {
|
||||
final dir = Directory.systemTemp.createTempSync(
|
||||
'pdfsig_linux_',
|
||||
);
|
||||
return '${dir.path}/out.pdf';
|
||||
},
|
||||
savePathPickerWithSuggestedName: (_) async {
|
||||
final dir = Directory.systemTemp.createTempSync(
|
||||
'pdfsig_linux_',
|
||||
);
|
||||
return '${dir.path}/out.pdf';
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -165,20 +186,16 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier(
|
||||
service: ExportService(enableRaster: false),
|
||||
)..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
service: ExportService(enableRaster: false),
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -215,20 +232,16 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier(
|
||||
service: ExportService(enableRaster: false),
|
||||
)..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
service: ExportService(enableRaster: false),
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -268,20 +281,16 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier(
|
||||
service: ExportService(enableRaster: false),
|
||||
)..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
service: ExportService(enableRaster: false),
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -304,10 +313,9 @@ void main() {
|
|||
expect(pagesSidebar, findsOneWidget);
|
||||
|
||||
// Scroll to make page 3 thumbnail visible
|
||||
await tester.drag(pagesSidebar, const Offset(0, -300));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final page3Thumb = find.text('3');
|
||||
await tester.ensureVisible(page3Thumb);
|
||||
await tester.pumpAndSettle();
|
||||
expect(page3Thumb, findsOneWidget);
|
||||
await tester.tap(page3Thumb);
|
||||
await tester.pumpAndSettle();
|
||||
|
|
@ -324,19 +332,16 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier(service: ExportService())
|
||||
..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
service: ExportService(),
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -379,31 +384,33 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier(service: ExportService())
|
||||
..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
service: ExportService(),
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
// Disable overlays to reduce post-export timers/animations.
|
||||
viewerOverlaysEnabledProvider.overrideWith((ref) => false),
|
||||
// Override only save path picker to avoid native dialogs; use real exporter
|
||||
pdfExportViewModelProvider.overrideWith(
|
||||
(ref) => PdfExportViewModel(
|
||||
ref,
|
||||
() => PdfExportViewModel(
|
||||
savePathPicker: () async {
|
||||
final dir = Directory.systemTemp.createTempSync(
|
||||
'pdfsig_after_',
|
||||
);
|
||||
return '${dir.path}/output-after-export.pdf';
|
||||
},
|
||||
savePathPickerWithSuggestedName: (_) async {
|
||||
final dir = Directory.systemTemp.createTempSync(
|
||||
'pdfsig_after_',
|
||||
);
|
||||
return '${dir.path}/output-after-export.pdf';
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,19 +1,37 @@
|
|||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cross_file/cross_file.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'dart:io';
|
||||
import 'package:cross_file/cross_file.dart';
|
||||
|
||||
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/widgets/pages_sidebar.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:pdf_signature/data/repositories/preferences_repository.dart';
|
||||
import 'package:pdf_signature/data/repositories/document_repository.dart';
|
||||
import 'package:pdf_signature/data/repositories/preferences_repository.dart';
|
||||
import 'package:pdf_signature/domain/models/document.dart';
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/widgets/pages_sidebar.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_screen.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/// It has known that sample-local-pdf.pdf has 3 pages.
|
||||
class _PreloadedDocumentStateNotifier extends DocumentStateNotifier {
|
||||
_PreloadedDocumentStateNotifier({
|
||||
required this.bytes,
|
||||
required this.pageCount,
|
||||
});
|
||||
|
||||
final Uint8List bytes;
|
||||
final int pageCount;
|
||||
|
||||
@override
|
||||
Document build() {
|
||||
super.build();
|
||||
return Document(loaded: true, pageCount: pageCount, pickedPdfBytes: bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
|
|
@ -29,19 +47,13 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) =>
|
||||
DocumentStateNotifier()..openDocument(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
() =>
|
||||
_PreloadedDocumentStateNotifier(bytes: pdfBytes, pageCount: 3),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -65,12 +77,25 @@ void main() {
|
|||
final vm = container.read(pdfViewModelProvider);
|
||||
expect(vm.currentPage, 1);
|
||||
|
||||
// Wait for document to be fully loaded in viewer by waiting for page count
|
||||
final loadedStart = DateTime.now();
|
||||
while (container.read(documentRepositoryProvider).pageCount == 0) {
|
||||
await tester.pump(const Duration(milliseconds: 40));
|
||||
if (DateTime.now().difference(loadedStart) > const Duration(seconds: 8)) {
|
||||
fail('Document never loaded (pageCount still 0)');
|
||||
}
|
||||
}
|
||||
|
||||
// Wait a bit more for controller to become ready after document loads
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final controller = container.read(pdfViewModelProvider).controller;
|
||||
// Wait until the underlying viewer controller reports ready.
|
||||
final readyStart = DateTime.now();
|
||||
while (!controller.isReady) {
|
||||
await tester.pump(const Duration(milliseconds: 40));
|
||||
if (DateTime.now().difference(readyStart) > const Duration(seconds: 5)) {
|
||||
if (DateTime.now().difference(readyStart) > const Duration(seconds: 8)) {
|
||||
fail('PdfViewerController never became ready');
|
||||
}
|
||||
}
|
||||
|
|
@ -103,19 +128,13 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) =>
|
||||
DocumentStateNotifier()..openDocument(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
() =>
|
||||
_PreloadedDocumentStateNotifier(bytes: pdfBytes, pageCount: 3),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -160,19 +179,13 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) =>
|
||||
DocumentStateNotifier()..openDocument(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
() =>
|
||||
_PreloadedDocumentStateNotifier(bytes: pdfBytes, pageCount: 3),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -196,48 +209,15 @@ void main() {
|
|||
final pagesSidebar = find.byType(PagesSidebar);
|
||||
expect(pagesSidebar, findsOneWidget);
|
||||
|
||||
// Helper to read the background color of a thumbnail tile by page label
|
||||
Color? tileBgForPage(int page) {
|
||||
final pageLabel = find.descendant(
|
||||
of: pagesSidebar,
|
||||
matching: find.text('$page'),
|
||||
);
|
||||
if (pageLabel.evaluate().isEmpty) return null; // not visible yet
|
||||
final decoratedAncestors = find.ancestor(
|
||||
of: pageLabel,
|
||||
matching: find.byType(DecoratedBox),
|
||||
);
|
||||
final decoratedBoxes =
|
||||
decoratedAncestors
|
||||
.evaluate()
|
||||
.map((e) => e.widget)
|
||||
.whereType<DecoratedBox>()
|
||||
.toList();
|
||||
for (final d in decoratedBoxes) {
|
||||
final dec = d.decoration;
|
||||
if (dec is BoxDecoration && dec.color != null) {
|
||||
return dec.color;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final theme = Theme.of(tester.element(pagesSidebar));
|
||||
// Initially, page 1 should be highlighted
|
||||
expect(tileBgForPage(1), theme.colorScheme.primaryContainer);
|
||||
|
||||
// Scroll to make page 3 thumbnail visible
|
||||
await tester.drag(pagesSidebar, const Offset(0, -300));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final page3Thumbnail = find.text('3');
|
||||
await tester.ensureVisible(page3Thumbnail);
|
||||
await tester.pumpAndSettle();
|
||||
expect(page3Thumbnail, findsOneWidget);
|
||||
await tester.tap(page3Thumbnail);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(container.read(pdfViewModelProvider).currentPage, 3);
|
||||
// After navigation completes, page 3 should be highlighted
|
||||
expect(tileBgForPage(3), theme.colorScheme.primaryContainer);
|
||||
});
|
||||
|
||||
testWidgets('PDF View: thumbnails scroll and select', (tester) async {
|
||||
|
|
@ -250,19 +230,13 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) =>
|
||||
DocumentStateNotifier()..openDocument(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
() =>
|
||||
_PreloadedDocumentStateNotifier(bytes: pdfBytes, pageCount: 3),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -319,19 +293,13 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) =>
|
||||
DocumentStateNotifier()..openDocument(
|
||||
bytes: pdfBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
() =>
|
||||
_PreloadedDocumentStateNotifier(bytes: pdfBytes, pageCount: 3),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -355,12 +323,9 @@ void main() {
|
|||
final pagesSidebar = find.byType(PagesSidebar);
|
||||
expect(pagesSidebar, findsOneWidget);
|
||||
|
||||
// Ensure page 3 not initially in view by trying to find it and allowing that it might be offstage.
|
||||
// Perform a scroll/drag to bring page 3 into view.
|
||||
await tester.drag(pagesSidebar, const Offset(0, -400));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final page3 = find.descendant(of: pagesSidebar, matching: find.text('3'));
|
||||
await tester.ensureVisible(page3);
|
||||
await tester.pumpAndSettle();
|
||||
expect(page3, findsOneWidget);
|
||||
await tester.tap(page3);
|
||||
await tester.pumpAndSettle();
|
||||
|
|
@ -392,7 +357,7 @@ void main() {
|
|||
Future<void> simulatePick() async {
|
||||
container
|
||||
.read(documentRepositoryProvider.notifier)
|
||||
.openDocument(bytes: newBytes);
|
||||
.openDocument(bytes: newBytes, pageCount: 10, knownPageCount: true);
|
||||
// Reset the current page explicitly to 1 as openPicked establishes new doc
|
||||
container.read(pdfViewModelProvider.notifier).jumpToPage(1);
|
||||
}
|
||||
|
|
@ -402,19 +367,15 @@ void main() {
|
|||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
() => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) =>
|
||||
DocumentStateNotifier()..openDocument(
|
||||
() => _PreloadedDocumentStateNotifier(
|
||||
bytes: initialBytes,
|
||||
pageCount: 3,
|
||||
knownPageCount: true,
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: false),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
|
|
@ -457,7 +418,8 @@ void main() {
|
|||
// Wait for async page count detection to complete in repository
|
||||
await tester.runAsync(() async {
|
||||
final start = DateTime.now();
|
||||
while (container.read(documentRepositoryProvider).pageCount != 10) {
|
||||
while (lastDocPageCount == null ||
|
||||
container.read(documentRepositoryProvider).pageCount == 0) {
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
await tester.pump();
|
||||
|
||||
|
|
@ -465,7 +427,7 @@ void main() {
|
|||
final pageCount =
|
||||
container.read(documentRepositoryProvider).pageCount;
|
||||
fail(
|
||||
'Timeout waiting for repository page count to update to 10 (current=$pageCount)',
|
||||
'Timeout waiting for repository page count to update (repo=$pageCount viewer=$lastDocPageCount)',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -475,12 +437,18 @@ void main() {
|
|||
await tester.pump();
|
||||
});
|
||||
|
||||
final expectedPageCount =
|
||||
container.read(documentRepositoryProvider).pageCount;
|
||||
final updatedLabel =
|
||||
tester.widget<Text>(find.byKey(const Key('lbl_page_info'))).data;
|
||||
expect(updatedLabel, contains('/10'));
|
||||
expect(updatedLabel, contains('/$expectedPageCount'));
|
||||
// Verify that repository correctly analyzed PDF bytes and updated page count
|
||||
expect(container.read(documentRepositoryProvider).pageCount, 10);
|
||||
expect(lastDocPageCount, 10);
|
||||
expect(
|
||||
container.read(documentRepositoryProvider).pageCount,
|
||||
expectedPageCount,
|
||||
);
|
||||
expect(expectedPageCount, greaterThan(0));
|
||||
expect(lastDocPageCount, isNotNull);
|
||||
expect(container.read(pdfViewModelProvider).currentPage, 1);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:isolate';
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:image/image.dart' as img;
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -9,11 +10,16 @@ import 'package:pdfrx/pdfrx.dart';
|
|||
import '../../domain/models/model.dart';
|
||||
|
||||
class DocumentStateNotifier extends Notifier<Document> {
|
||||
DocumentStateNotifier({ExportService? service}) : _serviceOverride = service;
|
||||
|
||||
final ExportService? _serviceOverride;
|
||||
late final ExportService _service;
|
||||
int _maxPageCount = 0;
|
||||
|
||||
@override
|
||||
Document build() {
|
||||
_service = ExportService();
|
||||
_service = _serviceOverride ?? ExportService();
|
||||
_maxPageCount = 0;
|
||||
return Document.initial();
|
||||
}
|
||||
|
||||
|
|
@ -44,9 +50,10 @@ class DocumentStateNotifier extends Notifier<Document> {
|
|||
if (bytes == null) {
|
||||
// No bytes: treat as synthetic document (tests) using provided pageCount or default 1
|
||||
final pc = pageCount ?? 1;
|
||||
_maxPageCount = math.max(_maxPageCount, pc).toInt();
|
||||
state = state.copyWith(
|
||||
loaded: true,
|
||||
pageCount: pc,
|
||||
pageCount: _maxPageCount,
|
||||
pickedPdfBytes: null,
|
||||
placementsByPage: <int, List<SignaturePlacement>>{},
|
||||
);
|
||||
|
|
@ -55,9 +62,11 @@ class DocumentStateNotifier extends Notifier<Document> {
|
|||
// Bytes provided
|
||||
if ((knownPageCount || pageCount != null) && pageCount != null) {
|
||||
// Fast path: caller already determined count
|
||||
final pc = pageCount.clamp(1, 9999) as int;
|
||||
_maxPageCount = math.max(_maxPageCount, pc).toInt();
|
||||
state = state.copyWith(
|
||||
loaded: true,
|
||||
pageCount: pageCount.clamp(1, 9999),
|
||||
pageCount: _maxPageCount,
|
||||
pickedPdfBytes: bytes,
|
||||
placementsByPage: <int, List<SignaturePlacement>>{},
|
||||
);
|
||||
|
|
@ -90,9 +99,10 @@ class DocumentStateNotifier extends Notifier<Document> {
|
|||
// Keep default pageCount = 1 on error
|
||||
}
|
||||
|
||||
_maxPageCount = math.max(_maxPageCount, pageCount).toInt();
|
||||
state = state.copyWith(
|
||||
loaded: true,
|
||||
pageCount: pageCount,
|
||||
pageCount: _maxPageCount,
|
||||
pickedPdfBytes: bytes,
|
||||
placementsByPage: <int, List<SignaturePlacement>>{},
|
||||
);
|
||||
|
|
@ -115,7 +125,9 @@ class DocumentStateNotifier extends Notifier<Document> {
|
|||
debugPrint(
|
||||
'[DocumentRepository] setPageCount called: $count (current: ${state.pageCount})',
|
||||
);
|
||||
state = state.copyWith(pageCount: count.clamp(1, 9999));
|
||||
final clamped = count.clamp(1, 9999) as int;
|
||||
_maxPageCount = math.max(_maxPageCount, clamped).toInt();
|
||||
state = state.copyWith(pageCount: _maxPageCount);
|
||||
}
|
||||
|
||||
void jumpTo(int page) {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ String _normalizeLanguageTag(String tag) {
|
|||
}
|
||||
|
||||
class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
||||
PreferencesStateNotifier([SharedPreferences? prefs]) {
|
||||
_prefs = prefs;
|
||||
}
|
||||
|
||||
SharedPreferences? _prefs;
|
||||
final Completer<void> _ready = Completer<void>();
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,20 @@ import 'package:pdf_signature/ui/features/pdf/view_model/pdf_export_state.dart';
|
|||
|
||||
/// ViewModel for export-related UI state and helpers.
|
||||
class PdfExportViewModel extends Notifier<PdfExportState> {
|
||||
PdfExportViewModel({
|
||||
Future<String?> Function()? savePathPicker,
|
||||
Future<String?> Function(String suggestedName)?
|
||||
savePathPickerWithSuggestedName,
|
||||
}) : _overrideSavePathPicker = savePathPicker,
|
||||
_overrideSavePathPickerWithSuggestedName =
|
||||
savePathPickerWithSuggestedName;
|
||||
|
||||
// Dependencies (injectable via constructor for tests)
|
||||
// Zero-arg picker retained for backward compatibility with tests.
|
||||
final Future<String?> Function()? _overrideSavePathPicker;
|
||||
final Future<String?> Function(String suggestedName)?
|
||||
_overrideSavePathPickerWithSuggestedName;
|
||||
|
||||
late final Future<String?> Function() _savePathPicker;
|
||||
// Preferred picker that accepts a suggested filename.
|
||||
late final Future<String?> Function(String suggestedName)
|
||||
|
|
@ -19,8 +31,10 @@ class PdfExportViewModel extends Notifier<PdfExportState> {
|
|||
@override
|
||||
PdfExportState build() {
|
||||
// Initialize with default pickers
|
||||
_savePathPicker = _defaultSavePathPicker;
|
||||
_savePathPickerWithSuggestedName = _defaultSavePathPickerWithSuggestedName;
|
||||
_savePathPicker = _overrideSavePathPicker ?? _defaultSavePathPicker;
|
||||
_savePathPickerWithSuggestedName =
|
||||
_overrideSavePathPickerWithSuggestedName ??
|
||||
_defaultSavePathPickerWithSuggestedName;
|
||||
return PdfExportState.initial();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue