feat(flyer-import): add session management and retrieval endpoints
Test Suite / backend-pr-quick (push) Has been skipped
Test Suite / quick-import-pr-quick (push) Has been skipped
Test Suite / backend-full (push) Successful in 2m15s
Test Suite / flutter-quality (push) Failing after 1m25s

- Add new API endpoints for retrieving flyer import sessions:
  - GET /flyer-import/sessions/latest - Retrieve latest session for user
  - GET /flyer-import/sessions/:sessionId - Retrieve specific session
- Implement session persistence and restoration in Flutter UI
- Add toJson() methods to FlyerImportItem and FlyerImportResult for serialization
- Add new FlyerImportSession domain model for local session management
- Add unit test file for FlyerImportService
- Update FlyerImportController with new endpoints and user ID extraction
- Update FlyerImportService with session retrieval logic and response mapping
- Update API paths in Flutter client
- Add session restoration on widget init in FlyerImportTab
This commit is contained in:
Nils-Johan Gynther
2026-05-19 21:55:55 +02:00
parent 8b8f8b7b6f
commit 6cd5b80adb
10 changed files with 649 additions and 30 deletions
@@ -0,0 +1,69 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:recipe_flutter/features/import/data/flyer_import_session.dart';
import 'package:recipe_flutter/features/import/domain/flyer_import_item.dart';
import 'package:recipe_flutter/features/import/domain/flyer_import_result.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('FlyerImportSessionNotifier', () {
setUp(() async {
SharedPreferences.setMockInitialValues({});
});
test('persists only lightweight session payload', () async {
final container = ProviderContainer();
addTearDown(container.dispose);
final notifier = container.read(flyerImportSessionProvider.notifier);
notifier.setImportedResult(
result: FlyerImportResult(
sessionId: 12,
items: [
FlyerImportItem(
flyerItemId: 1,
rawName: 'Tomat',
normalizedName: 'tomat',
isOffer: true,
),
],
warnings: const [],
),
selected: const {0: true},
fileName: 'flyer.pdf',
);
await Future<void>.delayed(Duration.zero);
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString('flyer_import_session_v1');
expect(raw, isNotNull);
expect(raw!, isNot(contains('rawName')));
expect(raw, isNot(contains('normalizedName')));
expect(raw, contains('"sessionId":12'));
});
test('restore reads sessionId and selection from storage', () async {
SharedPreferences.setMockInitialValues({
'flyer_import_session_v1': '{"sessionId":77,"fileName":"flyer.pdf","selected":{"0":true,"2":false}}',
});
final container = ProviderContainer();
addTearDown(container.dispose);
final notifier = container.read(flyerImportSessionProvider.notifier);
await notifier.restore();
final restored = container.read(flyerImportSessionProvider);
expect(restored, isNotNull);
expect(restored!.sessionId, 77);
expect(restored.fileName, 'flyer.pdf');
expect(restored.selected[0], true);
expect(restored.selected[2], false);
expect(restored.result, isNull);
});
});
}