test: resolve error for `flutter test` after upgrade to riverpod3
This commit is contained in:
parent
0587e50360
commit
d6bb64b3bc
|
|
@ -90,12 +90,17 @@ String _normalizeLanguageTag(String tag) {
|
|||
}
|
||||
|
||||
class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
||||
late final SharedPreferences _prefs;
|
||||
SharedPreferences? _prefs;
|
||||
final Completer<void> _ready = Completer<void>();
|
||||
|
||||
@override
|
||||
PreferencesState build() {
|
||||
// Initialize with defaults
|
||||
// If _prefs was already set by initWithPrefs (for testing), use it
|
||||
if (_prefs != null) {
|
||||
return _buildFromPrefs(_prefs!);
|
||||
}
|
||||
|
||||
// Initialize with defaults for production
|
||||
final defaultState = PreferencesState(
|
||||
theme: 'system',
|
||||
language: _normalizeLanguageTag(
|
||||
|
|
@ -115,11 +120,24 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
_ready.complete();
|
||||
}
|
||||
|
||||
// For testing - can be called with mock SharedPreferences
|
||||
// For testing - can be called with mock SharedPreferences BEFORE build
|
||||
void initWithPrefs(SharedPreferences prefs) {
|
||||
_prefs = prefs;
|
||||
_load();
|
||||
_ready.complete();
|
||||
}
|
||||
|
||||
PreferencesState _buildFromPrefs(SharedPreferences prefs) {
|
||||
final loaded = PreferencesState(
|
||||
theme: prefs.getString(_kTheme) ?? 'system',
|
||||
language: _normalizeLanguageTag(
|
||||
prefs.getString(_kLanguage) ??
|
||||
WidgetsBinding.instance.platformDispatcher.locale.toLanguageTag(),
|
||||
),
|
||||
exportDpi: _readDpi(prefs),
|
||||
theme_color: prefs.getString(_kThemeColor) ?? '#FF2196F3',
|
||||
);
|
||||
// Complete ready immediately for tests
|
||||
if (!_ready.isCompleted) _ready.complete();
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static Color? _tryParseColor(String? s) {
|
||||
|
|
@ -193,15 +211,16 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
if (_prefs == null) return;
|
||||
// Load persisted values (with sane defaults)
|
||||
final loaded = PreferencesState(
|
||||
theme: _prefs.getString(_kTheme) ?? 'system',
|
||||
theme: _prefs!.getString(_kTheme) ?? 'system',
|
||||
language: _normalizeLanguageTag(
|
||||
_prefs.getString(_kLanguage) ??
|
||||
_prefs!.getString(_kLanguage) ??
|
||||
WidgetsBinding.instance.platformDispatcher.locale.toLanguageTag(),
|
||||
),
|
||||
exportDpi: _readDpi(_prefs),
|
||||
theme_color: _prefs.getString(_kThemeColor) ?? '#FF2196F3',
|
||||
exportDpi: _readDpi(_prefs!),
|
||||
theme_color: _prefs!.getString(_kThemeColor) ?? '#FF2196F3',
|
||||
);
|
||||
state = loaded;
|
||||
_ensureValid();
|
||||
|
|
@ -222,21 +241,22 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
}
|
||||
|
||||
void _ensureValid() {
|
||||
if (_prefs == null) return;
|
||||
final themeValid = {'light', 'dark', 'system'};
|
||||
if (!themeValid.contains(state.theme)) {
|
||||
state = state.copyWith(theme: 'system');
|
||||
_prefs.setString(_kTheme, 'system');
|
||||
_prefs!.setString(_kTheme, 'system');
|
||||
}
|
||||
final normalized = _normalizeLanguageTag(state.language);
|
||||
if (normalized != state.language) {
|
||||
state = state.copyWith(language: normalized);
|
||||
_prefs.setString(_kLanguage, normalized);
|
||||
_prefs!.setString(_kLanguage, normalized);
|
||||
}
|
||||
// Ensure DPI is one of allowed values
|
||||
const allowed = [96.0, 144.0, 200.0, 300.0];
|
||||
if (!allowed.contains(state.exportDpi)) {
|
||||
state = state.copyWith(exportDpi: 144.0);
|
||||
_prefs.setDouble(_kExportDpi, 144.0);
|
||||
_prefs!.setDouble(_kExportDpi, 144.0);
|
||||
}
|
||||
// Ensure theme color is a valid hex or known name; normalize to hex
|
||||
final parsed = _tryParseColor(state.theme_color);
|
||||
|
|
@ -244,12 +264,12 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
final fallback = Colors.blue;
|
||||
final hex = _toHex(fallback);
|
||||
state = state.copyWith(theme_color: hex);
|
||||
_prefs.setString(_kThemeColor, hex);
|
||||
_prefs!.setString(_kThemeColor, hex);
|
||||
} else {
|
||||
final hex = _toHex(parsed);
|
||||
if (state.theme_color != hex) {
|
||||
state = state.copyWith(theme_color: hex);
|
||||
_prefs.setString(_kThemeColor, hex);
|
||||
_prefs!.setString(_kThemeColor, hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -259,14 +279,14 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
if (!valid.contains(theme)) return;
|
||||
state = state.copyWith(theme: theme);
|
||||
await _ensureReady();
|
||||
await _prefs.setString(_kTheme, theme);
|
||||
await _prefs!.setString(_kTheme, theme);
|
||||
}
|
||||
|
||||
Future<void> setLanguage(String language) async {
|
||||
final normalized = _normalizeLanguageTag(language);
|
||||
state = state.copyWith(language: normalized);
|
||||
await _ensureReady();
|
||||
await _prefs.setString(_kLanguage, normalized);
|
||||
await _prefs!.setString(_kLanguage, normalized);
|
||||
}
|
||||
|
||||
Future<void> setThemeColor(String themeColor) async {
|
||||
|
|
@ -275,7 +295,7 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
final hex = _toHex(c);
|
||||
state = state.copyWith(theme_color: hex);
|
||||
await _ensureReady();
|
||||
await _prefs.setString(_kThemeColor, hex);
|
||||
await _prefs!.setString(_kThemeColor, hex);
|
||||
}
|
||||
|
||||
Future<void> resetToDefaults() async {
|
||||
|
|
@ -289,11 +309,11 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
theme_color: '#FF2196F3',
|
||||
);
|
||||
await _ensureReady();
|
||||
await _prefs.setString(_kTheme, 'system');
|
||||
await _prefs.setString(_kLanguage, normalized);
|
||||
await _prefs.setString(_kPageView, 'continuous');
|
||||
await _prefs.setDouble(_kExportDpi, 144.0);
|
||||
await _prefs.setString(_kThemeColor, '#FF2196F3');
|
||||
await _prefs!.setString(_kTheme, 'system');
|
||||
await _prefs!.setString(_kLanguage, normalized);
|
||||
await _prefs!.setString(_kPageView, 'continuous');
|
||||
await _prefs!.setDouble(_kExportDpi, 144.0);
|
||||
await _prefs!.setString(_kThemeColor, '#FF2196F3');
|
||||
}
|
||||
|
||||
Future<void> setExportDpi(double dpi) async {
|
||||
|
|
@ -301,7 +321,7 @@ class PreferencesStateNotifier extends Notifier<PreferencesState> {
|
|||
if (!allowed.contains(dpi)) return;
|
||||
state = state.copyWith(exportDpi: dpi);
|
||||
await _ensureReady();
|
||||
await _prefs.setDouble(_kExportDpi, dpi);
|
||||
await _prefs!.setDouble(_kExportDpi, dpi);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ class PdfViewModel extends Notifier<PdfViewState> {
|
|||
|
||||
// Get current document source name for PdfDocumentRefData
|
||||
String get documentSourceName {
|
||||
// Ensure document version is up to date, but only update if really needed
|
||||
_updateDocumentVersionIfNeeded();
|
||||
// Return the current source name without updating state
|
||||
// State updates should be done explicitly via updateDocumentVersionIfNeeded()
|
||||
return state.documentVersion.sourceName;
|
||||
}
|
||||
|
||||
void _updateDocumentVersionIfNeeded() {
|
||||
void updateDocumentVersionIfNeeded() {
|
||||
final document = ref.read(documentRepositoryProvider);
|
||||
if (!identical(state.documentVersion.lastBytes, document.pickedPdfBytes)) {
|
||||
state = state.copyWith(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/document_version.dart';
|
||||
import 'package:pdfrx/pdfrx.dart';
|
||||
|
||||
|
|
@ -21,12 +22,12 @@ class PdfViewState {
|
|||
});
|
||||
|
||||
factory PdfViewState.initial({bool? useMockViewer}) {
|
||||
// Default to false (no mocking) - tests should explicitly pass true if they want mock viewer
|
||||
final defaultUseMock = useMockViewer ?? false;
|
||||
return PdfViewState(
|
||||
controller: PdfViewerController(),
|
||||
currentPage: 1,
|
||||
useMockViewer:
|
||||
useMockViewer ??
|
||||
const bool.fromEnvironment('FLUTTER_TEST', defaultValue: false),
|
||||
useMockViewer: defaultUseMock,
|
||||
activeRect: null,
|
||||
lockedPlacements: const {},
|
||||
documentVersion: DocumentVersion.initial(),
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ class _PdfViewerWidgetState extends ConsumerState<PdfViewerWidget> {
|
|||
if (!identical(bytes, _lastBytes)) {
|
||||
_lastBytes = bytes;
|
||||
final viewModel = ref.read(pdfViewModelProvider.notifier);
|
||||
// Update document version outside of build
|
||||
Future.microtask(() {
|
||||
viewModel.updateDocumentVersionIfNeeded();
|
||||
});
|
||||
debugPrint(
|
||||
'[PdfViewerWidget] New PDF bytes detected -> ${viewModel.documentSourceName}',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -118,9 +118,11 @@ class SignatureOverlay extends ConsumerWidget {
|
|||
},
|
||||
// Keep default handles; you can customize later if needed
|
||||
contentBuilder: (context, boxRect, flip) {
|
||||
final isLocked = ref
|
||||
.read(pdfViewModelProvider.notifier)
|
||||
.isPlacementLocked(page: pageNumber, index: placedIndex);
|
||||
// Watch the provider state to rebuild when lock state changes
|
||||
final pdfViewState = ref.watch(pdfViewModelProvider);
|
||||
final isLocked = pdfViewState.lockedPlacements.contains(
|
||||
'${pageNumber}_$placedIndex',
|
||||
);
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
|
|
|
|||
|
|
@ -34,6 +34,19 @@ class FakeExportService extends ExportService {
|
|||
}
|
||||
}
|
||||
|
||||
class _TestDocumentStateNotifier extends DocumentStateNotifier {
|
||||
@override
|
||||
Document build() {
|
||||
// Initialize with sample document for tests, bypassing the parent build
|
||||
return Document.initial().copyWith(
|
||||
loaded: true,
|
||||
pageCount: 5,
|
||||
pickedPdfBytes: null,
|
||||
placementsByPage: <int, List<SignaturePlacement>>{},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<ProviderContainer> pumpApp(
|
||||
WidgetTester tester, {
|
||||
Map<String, Object> initialPrefs = const {},
|
||||
|
|
@ -42,18 +55,16 @@ Future<ProviderContainer> pumpApp(
|
|||
final prefs = await SharedPreferences.getInstance();
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
preferencesRepositoryProvider.overrideWith(() {
|
||||
final notifier = PreferencesStateNotifier();
|
||||
notifier.initWithPrefs(prefs);
|
||||
return notifier;
|
||||
}),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier()..openSample(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
pdfExportViewModelProvider.overrideWith(
|
||||
(ref) => PdfExportViewModel(ref, savePathPicker: () async => 'out.pdf'),
|
||||
() => _TestDocumentStateNotifier(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
pdfExportViewModelProvider.overrideWith(() => PdfExportViewModel()),
|
||||
],
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
|
|
|
|||
|
|
@ -99,8 +99,9 @@ class MockSignatureState {
|
|||
}) : strokes = strokes ?? [];
|
||||
}
|
||||
|
||||
class MockSignatureNotifier extends StateNotifier<MockSignatureState> {
|
||||
MockSignatureNotifier() : super(MockSignatureState());
|
||||
class MockSignatureNotifier extends Notifier<MockSignatureState> {
|
||||
@override
|
||||
MockSignatureState build() => MockSignatureState();
|
||||
|
||||
void setStrokes(List<List<Offset>> strokes) {
|
||||
state = MockSignatureState(
|
||||
|
|
@ -174,11 +175,32 @@ class MockSignatureNotifier extends StateNotifier<MockSignatureState> {
|
|||
}
|
||||
|
||||
final signatureProvider =
|
||||
StateNotifierProvider<MockSignatureNotifier, MockSignatureState>(
|
||||
(ref) => MockSignatureNotifier(),
|
||||
NotifierProvider<MockSignatureNotifier, MockSignatureState>(
|
||||
() => MockSignatureNotifier(),
|
||||
);
|
||||
|
||||
// Mock other providers
|
||||
final currentRectProvider = StateProvider<Rect?>((ref) => null);
|
||||
final editingEnabledProvider = StateProvider<bool>((ref) => false);
|
||||
final aspectLockedProvider = StateProvider<bool>((ref) => false);
|
||||
// Mock other providers using NotifierProvider instead of StateProvider
|
||||
class _CurrentRectNotifier extends Notifier<Rect?> {
|
||||
@override
|
||||
Rect? build() => null;
|
||||
}
|
||||
|
||||
class _EditingEnabledNotifier extends Notifier<bool> {
|
||||
@override
|
||||
bool build() => false;
|
||||
}
|
||||
|
||||
class _AspectLockedNotifier extends Notifier<bool> {
|
||||
@override
|
||||
bool build() => false;
|
||||
}
|
||||
|
||||
final currentRectProvider = NotifierProvider<_CurrentRectNotifier, Rect?>(
|
||||
() => _CurrentRectNotifier(),
|
||||
);
|
||||
final editingEnabledProvider = NotifierProvider<_EditingEnabledNotifier, bool>(
|
||||
() => _EditingEnabledNotifier(),
|
||||
);
|
||||
final aspectLockedProvider = NotifierProvider<_AspectLockedNotifier, bool>(
|
||||
() => _AspectLockedNotifier(),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ Future<void> aSignaturePlacementAppearsOnThePageBasedOnTheSignatureCard(
|
|||
) async {
|
||||
final container = TestWorld.container!;
|
||||
final pdf = container.read(documentRepositoryProvider);
|
||||
final page = container.read(pdfViewModelProvider);
|
||||
final placements = pdf.placementsByPage[page] ?? const [];
|
||||
final pdfView = container.read(pdfViewModelProvider);
|
||||
final currentPage = pdfView.currentPage;
|
||||
final placements = pdf.placementsByPage[currentPage] ?? const [];
|
||||
expect(
|
||||
placements.isNotEmpty,
|
||||
true,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ Future<void> onlyTheSelectedSignaturePlacementIsRemoved(
|
|||
) async {
|
||||
final container = TestWorld.container ?? ProviderContainer();
|
||||
final pdf = container.read(documentRepositoryProvider);
|
||||
final page = container.read(pdfViewModelProvider);
|
||||
final placements = pdf.placementsByPage[page] ?? const [];
|
||||
final pdfView = container.read(pdfViewModelProvider);
|
||||
final currentPage = pdfView.currentPage;
|
||||
final placements = pdf.placementsByPage[currentPage] ?? const [];
|
||||
expect(placements.length, 2); // Started with 3, removed 1, should have 2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,38 +32,19 @@ Future<void> theAppLaunches(WidgetTester tester) async {
|
|||
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier()..openSample(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
preferencesRepositoryProvider.overrideWith(() {
|
||||
final notifier = PreferencesStateNotifier();
|
||||
notifier.initWithPrefs(prefs);
|
||||
return notifier;
|
||||
}),
|
||||
documentRepositoryProvider.overrideWith(() => DocumentStateNotifier()),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
// Bridge: automatically mirror assets into signature cards so legacy
|
||||
// feature steps that expect SignatureCard widgets keep working even
|
||||
// though the production UI currently only stores raw assets.
|
||||
signatureCardRepositoryProvider.overrideWith((ref) {
|
||||
final notifier = _BridgedSignatureCardStateNotifier();
|
||||
ref.listen<List<SignatureAsset>>(signatureAssetRepositoryProvider, (
|
||||
prev,
|
||||
next,
|
||||
) {
|
||||
for (final asset in next) {
|
||||
if (!notifier.state.any((c) => identical(c.asset, asset))) {
|
||||
notifier.add(SignatureCard(asset: asset, rotationDeg: 0.0));
|
||||
}
|
||||
}
|
||||
// Remove cards whose assets were removed
|
||||
final remaining =
|
||||
notifier.state.where((c) => next.contains(c.asset)).toList();
|
||||
if (remaining.length != notifier.state.length) {
|
||||
notifier.setAll(remaining);
|
||||
}
|
||||
});
|
||||
return notifier;
|
||||
}),
|
||||
signatureCardRepositoryProvider.overrideWith(
|
||||
() => _BridgedSignatureCardStateNotifier(),
|
||||
),
|
||||
],
|
||||
);
|
||||
TestWorld.container = container;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ Future<void> theOtherSignaturePlacementsRemainUnchanged(
|
|||
) async {
|
||||
final container = TestWorld.container!;
|
||||
final pdf = container.read(documentRepositoryProvider);
|
||||
final page = container.read(pdfViewModelProvider);
|
||||
final placements = pdf.placementsByPage[page] ?? const [];
|
||||
final pdfView = container.read(pdfViewModelProvider);
|
||||
final currentPage = pdfView.currentPage;
|
||||
final placements = pdf.placementsByPage[currentPage] ?? const [];
|
||||
expect(placements.length, 2); // Should have 2 remaining after deleting 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,6 @@ Future<void> theUserOpensADifferentDocumentWithPages(
|
|||
}
|
||||
}
|
||||
// Moving to a new document should show page 1.
|
||||
container.read(pdfViewModelProvider).currentPage = 1;
|
||||
container.read(pdfViewModelProvider.notifier).jumpToPage(1);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,14 +13,17 @@ import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.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/l10n/app_localizations.dart';
|
||||
import 'package:pdf_signature/domain/models/model.dart';
|
||||
|
||||
// A fake export VM that always reports success, so this widget test doesn't
|
||||
// depend on PDF validity or platform specifics.
|
||||
bool exported = false;
|
||||
|
||||
class _FakePdfExportViewModel extends PdfExportViewModel {
|
||||
_FakePdfExportViewModel(Ref ref)
|
||||
: super(ref, savePathPicker: () async => 'C:/tmp/output.pdf');
|
||||
@override
|
||||
Future<String?> pickSavePathWithSuggestedName(String suggestedName) async {
|
||||
return '/fake/path/output.pdf'; // Return a fake path
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> exportToPath({
|
||||
|
|
@ -34,6 +37,18 @@ class _FakePdfExportViewModel extends PdfExportViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
class _TestDocumentStateNotifier extends DocumentStateNotifier {
|
||||
@override
|
||||
Document build() {
|
||||
return Document.initial().copyWith(
|
||||
loaded: true,
|
||||
pageCount: 5,
|
||||
pickedPdfBytes: Uint8List(0),
|
||||
placementsByPage: <int, List<SignaturePlacement>>{},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('Save uses file selector (via provider) and injected exporter', (
|
||||
tester,
|
||||
|
|
@ -43,22 +58,17 @@ void main() {
|
|||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
preferencesRepositoryProvider.overrideWith(
|
||||
(ref) => PreferencesStateNotifier(prefs),
|
||||
),
|
||||
preferencesRepositoryProvider.overrideWith(() {
|
||||
final notifier = PreferencesStateNotifier();
|
||||
notifier.initWithPrefs(prefs);
|
||||
return notifier;
|
||||
}),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) =>
|
||||
DocumentStateNotifier()..openDocument(
|
||||
bytes: Uint8List(0),
|
||||
pageCount: 5,
|
||||
knownPageCount: true,
|
||||
),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
() => _TestDocumentStateNotifier(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
pdfExportViewModelProvider.overrideWith(
|
||||
(ref) => _FakePdfExportViewModel(ref),
|
||||
() => _FakePdfExportViewModel(),
|
||||
),
|
||||
],
|
||||
child: MaterialApp(
|
||||
|
|
|
|||
|
|
@ -7,28 +7,102 @@ 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_view_state.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/domain/models/model.dart';
|
||||
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
// preferences_providers.dart no longer exports pageViewModeProvider
|
||||
|
||||
// Test helper classes
|
||||
class TestPdfViewModel extends PdfViewModel {
|
||||
@override
|
||||
PdfViewState build() {
|
||||
return PdfViewState.initial(useMockViewer: true);
|
||||
}
|
||||
}
|
||||
|
||||
class TestDocumentStateNotifier extends DocumentStateNotifier {
|
||||
@override
|
||||
Document build() {
|
||||
// Initialize with sample document for tests, bypassing the parent build
|
||||
return Document.initial().copyWith(
|
||||
loaded: true,
|
||||
pageCount: 5,
|
||||
pickedPdfBytes: null,
|
||||
placementsByPage: <int, List<SignaturePlacement>>{},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TestDocumentStateNotifierWithPlacements extends DocumentStateNotifier {
|
||||
final Uint8List pdfBytes;
|
||||
final List<int> signatureBytes;
|
||||
|
||||
TestDocumentStateNotifierWithPlacements(this.pdfBytes, this.signatureBytes);
|
||||
|
||||
@override
|
||||
Document build() {
|
||||
final image = img.decodeImage(Uint8List.fromList(signatureBytes))!;
|
||||
final asset = SignatureAsset(sigImage: image);
|
||||
|
||||
return Document.initial().copyWith(
|
||||
loaded: true,
|
||||
pageCount: 5,
|
||||
pickedPdfBytes: pdfBytes,
|
||||
placementsByPage: {
|
||||
1: [
|
||||
SignaturePlacement(
|
||||
rect: const Rect.fromLTWH(0.1, 0.1, 0.3, 0.2),
|
||||
asset: asset,
|
||||
),
|
||||
],
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Test notifier for SignatureCardRepository with pre-initialized card
|
||||
class TestSignatureCardStateNotifier extends SignatureCardStateNotifier {
|
||||
final List<int> signatureBytes;
|
||||
|
||||
TestSignatureCardStateNotifier(this.signatureBytes);
|
||||
@override
|
||||
List<SignatureCard> build() {
|
||||
// Initialize with a card already added
|
||||
final image = img.decodeImage(Uint8List.fromList(signatureBytes))!;
|
||||
final asset = SignatureAsset(sigImage: image, name: 'test');
|
||||
|
||||
return [SignatureCard(asset: asset, rotationDeg: 0.0)];
|
||||
}
|
||||
}
|
||||
|
||||
// Test notifier for SignatureAssetRepository with pre-loaded asset
|
||||
class TestSignatureAssetRepository extends SignatureAssetRepository {
|
||||
final List<int> signatureBytes;
|
||||
|
||||
TestSignatureAssetRepository(this.signatureBytes);
|
||||
@override
|
||||
List<SignatureAsset> build() {
|
||||
// Initialize with an asset already added
|
||||
final image = img.decodeImage(Uint8List.fromList(signatureBytes))!;
|
||||
return [SignatureAsset(sigImage: image, name: 'test')];
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> 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),
|
||||
() => TestDocumentStateNotifier(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => TestPdfViewModel()),
|
||||
pdfExportViewModelProvider.overrideWith(() => PdfExportViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -370,42 +444,18 @@ Future<void> pumpWithOpenPdfAndSig(WidgetTester tester) async {
|
|||
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;
|
||||
}),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
() => TestDocumentStateNotifierWithPlacements(pdfBytes, bytes),
|
||||
),
|
||||
signatureAssetRepositoryProvider.overrideWith(
|
||||
() => TestSignatureAssetRepository(bytes),
|
||||
),
|
||||
signatureCardRepositoryProvider.overrideWith(
|
||||
() => TestSignatureCardStateNotifier(bytes),
|
||||
),
|
||||
// In new model, interactive overlay not implemented; keep library empty
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
pdfExportViewModelProvider.overrideWith(
|
||||
(ref) => PdfExportViewModel(ref),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => TestPdfViewModel()),
|
||||
pdfExportViewModelProvider.overrideWith(() => PdfExportViewModel()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
|
|||
|
|
@ -5,15 +5,24 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
|
||||
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_view_state.dart';
|
||||
import 'package:pdf_signature/data/repositories/document_repository.dart';
|
||||
import 'package:pdf_signature/domain/models/model.dart';
|
||||
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
|
||||
class _TestPdfController extends DocumentStateNotifier {
|
||||
_TestPdfController() : super() {
|
||||
@override
|
||||
Document build() {
|
||||
// Start with a loaded multi-page doc, page 1 of 5
|
||||
state = Document.initial().copyWith(loaded: true, pageCount: 5);
|
||||
return Document.initial().copyWith(loaded: true, pageCount: 5);
|
||||
}
|
||||
}
|
||||
|
||||
class _TestPdfViewModel extends PdfViewModel {
|
||||
@override
|
||||
PdfViewState build() {
|
||||
return PdfViewState.initial(useMockViewer: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -24,12 +33,8 @@ void main() {
|
|||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => _TestPdfController(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => _TestPdfViewModel()),
|
||||
documentRepositoryProvider.overrideWith(() => _TestPdfController()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
|
|||
|
|
@ -7,13 +7,22 @@ import 'package:pdf_signature/ui/features/pdf/widgets/pdf_page_area.dart';
|
|||
import 'package:pdf_signature/data/repositories/document_repository.dart';
|
||||
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_state.dart';
|
||||
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
import 'package:pdf_signature/domain/models/model.dart';
|
||||
|
||||
class _TestPdfController extends DocumentStateNotifier {
|
||||
_TestPdfController() : super() {
|
||||
state = Document.initial().copyWith(loaded: true, pageCount: 6);
|
||||
@override
|
||||
Document build() {
|
||||
return Document.initial().copyWith(loaded: true, pageCount: 6);
|
||||
}
|
||||
}
|
||||
|
||||
class _TestPdfViewModel extends PdfViewModel {
|
||||
@override
|
||||
PdfViewState build() {
|
||||
return PdfViewState.initial(useMockViewer: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,10 +35,8 @@ void main() {
|
|||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith((ref) => ctrl),
|
||||
pdfViewModelProvider.overrideWith(() => _TestPdfViewModel()),
|
||||
documentRepositoryProvider.overrideWith(() => ctrl),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
|
|||
|
|
@ -7,13 +7,22 @@ import 'package:pdf_signature/ui/features/pdf/widgets/pdf_page_area.dart';
|
|||
import 'package:pdf_signature/data/repositories/document_repository.dart';
|
||||
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_state.dart';
|
||||
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
import 'package:pdf_signature/domain/models/model.dart';
|
||||
|
||||
class _TestPdfController extends DocumentStateNotifier {
|
||||
_TestPdfController() : super() {
|
||||
state = Document.initial().copyWith(loaded: true, pageCount: 6);
|
||||
@override
|
||||
Document build() {
|
||||
return Document.initial().copyWith(loaded: true, pageCount: 6);
|
||||
}
|
||||
}
|
||||
|
||||
class _TestPdfViewModel extends PdfViewModel {
|
||||
@override
|
||||
PdfViewState build() {
|
||||
return PdfViewState.initial(useMockViewer: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,11 +35,9 @@ void main() {
|
|||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => _TestPdfViewModel()),
|
||||
// Continuous mode is always-on; no page view override needed
|
||||
documentRepositoryProvider.overrideWith((ref) => ctrl),
|
||||
documentRepositoryProvider.overrideWith(() => ctrl),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
|
|||
|
|
@ -7,14 +7,24 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:pdf_signature/ui/features/pdf/widgets/pdf_page_area.dart';
|
||||
import 'package:pdf_signature/data/repositories/document_repository.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_model.dart';
|
||||
import 'package:pdf_signature/ui/features/pdf/view_model/pdf_view_state.dart';
|
||||
import 'package:pdfrx/pdfrx.dart';
|
||||
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
import 'package:pdf_signature/domain/models/model.dart';
|
||||
import 'helpers.dart';
|
||||
|
||||
class _TestPdfController extends DocumentStateNotifier {
|
||||
_TestPdfController() : super() {
|
||||
state = Document.initial().copyWith(loaded: true, pageCount: 6);
|
||||
@override
|
||||
Document build() {
|
||||
return Document.initial().copyWith(loaded: true, pageCount: 6);
|
||||
}
|
||||
}
|
||||
|
||||
class _TestPdfViewModel extends PdfViewModel {
|
||||
@override
|
||||
PdfViewState build() {
|
||||
return PdfViewState.initial(useMockViewer: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -25,12 +35,8 @@ void main() {
|
|||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => _TestPdfController(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => _TestPdfViewModel()),
|
||||
documentRepositoryProvider.overrideWith(() => _TestPdfController()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
|
@ -65,11 +71,9 @@ void main() {
|
|||
// Use a persistent container across rebuilds
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => _TestPdfViewModel()),
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier()..openSample(),
|
||||
() => TestDocumentStateNotifier(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import 'package:pdf_signature/data/repositories/document_repository.dart';
|
|||
import 'package:pdf_signature/domain/models/model.dart';
|
||||
import 'package:pdf_signature/l10n/app_localizations.dart';
|
||||
|
||||
import 'helpers.dart';
|
||||
|
||||
void main() {
|
||||
late ProviderContainer container;
|
||||
late SignatureAsset testAsset;
|
||||
|
|
@ -37,11 +39,9 @@ void main() {
|
|||
container = ProviderContainer(
|
||||
overrides: [
|
||||
documentRepositoryProvider.overrideWith(
|
||||
(ref) => DocumentStateNotifier()..openSample(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(
|
||||
(ref) => PdfViewModel(ref, useMockViewer: true),
|
||||
() => TestDocumentStateNotifier(),
|
||||
),
|
||||
pdfViewModelProvider.overrideWith(() => PdfViewModel()),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue