Save the current market search (query + facets) and get notified when a matching offer appears in your zone while the app is open, with a catch-up scan on start. Adds a save affordance in the search bar, a saved-searches list (apply/delete) with a per-search new-match badge, an AppBar entry badged with the unseen total, and notification-tap routing to the list. Alerts evaluate against the user's current area, dedup via seen keys, and skip own/blocked/hidden/non-active offers. en+es strings.
74 lines
2.4 KiB
Dart
74 lines
2.4 KiB
Dart
import 'package:commons_core/commons_core.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:tane/i18n/strings.g.dart';
|
|
import 'package:tane/services/saved_searches_store.dart';
|
|
import 'package:tane/ui/saved_searches_screen.dart';
|
|
|
|
import '../support/test_support.dart';
|
|
|
|
Widget _wrap(Widget child) {
|
|
LocaleSettings.setLocaleSync(AppLocale.en);
|
|
return TranslationProvider(
|
|
child: MaterialApp(
|
|
locale: AppLocale.en.flutterLocale,
|
|
supportedLocales: AppLocaleUtils.supportedLocales,
|
|
localizationsDelegates: const [
|
|
GlobalMaterialLocalizations.delegate,
|
|
GlobalWidgetsLocalizations.delegate,
|
|
GlobalCupertinoLocalizations.delegate,
|
|
],
|
|
home: child,
|
|
),
|
|
);
|
|
}
|
|
|
|
SavedSearch _search(String id, {String label = 'Tomatoes'}) =>
|
|
SavedSearch(id: id, label: label, query: 'tomato', createdAt: 1);
|
|
|
|
void main() {
|
|
testWidgets('shows the empty state when nothing is saved', (tester) async {
|
|
final store = SavedSearchesStore(InMemorySecretStore());
|
|
addTearDown(store.close);
|
|
|
|
await tester.pumpWidget(_wrap(SavedSearchesScreen(store: store)));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(
|
|
find.textContaining('No saved searches yet'),
|
|
findsOneWidget,
|
|
);
|
|
});
|
|
|
|
testWidgets('lists a saved search and its new-match badge', (tester) async {
|
|
final store = SavedSearchesStore(InMemorySecretStore());
|
|
addTearDown(store.close);
|
|
await store.save(_search('a'));
|
|
await store.markMatched('a', 'author:o1');
|
|
|
|
await tester.pumpWidget(_wrap(SavedSearchesScreen(store: store)));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Tomatoes'), findsOneWidget);
|
|
expect(find.text('1 new'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('delete confirms then removes the search', (tester) async {
|
|
final store = SavedSearchesStore(InMemorySecretStore());
|
|
addTearDown(store.close);
|
|
await store.save(_search('a'));
|
|
|
|
await tester.pumpWidget(_wrap(SavedSearchesScreen(store: store)));
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.tap(find.byKey(const Key('savedSearches.delete.a')));
|
|
await tester.pumpAndSettle();
|
|
// Confirm in the dialog.
|
|
await tester.tap(find.widgetWithText(FilledButton, 'Delete'));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Tomatoes'), findsNothing);
|
|
expect(await store.exists('a'), isFalse);
|
|
});
|
|
}
|