new plus button
This commit is contained in:
@@ -4,7 +4,7 @@ import 'package:receipity/services/backup_format.dart';
|
||||
void main() {
|
||||
test('round-trips a backup document', () {
|
||||
const original = BackupDocument(
|
||||
version: 2,
|
||||
version: 3,
|
||||
exportedAt: '2026-08-29T12:00:00.000',
|
||||
darkMode: true,
|
||||
supermarkets: [
|
||||
@@ -29,6 +29,7 @@ void main() {
|
||||
{
|
||||
'id': 8,
|
||||
'supermarket': 'Jumbo',
|
||||
'name': 'Weekly shop',
|
||||
'shopped_at': '2026-08-29T12:00:00.000',
|
||||
'receipt_image_path': 'receipts/shop_8.jpg',
|
||||
'total': 1.5,
|
||||
@@ -46,6 +47,9 @@ void main() {
|
||||
'unit_price': 1.5,
|
||||
},
|
||||
],
|
||||
shopTags: [
|
||||
{'id': 1, 'shop_id': 8, 'tag': 'weekly', 'normalized_tag': 'weekly'},
|
||||
],
|
||||
shoppingLists: [
|
||||
{
|
||||
'id': 1,
|
||||
@@ -71,7 +75,9 @@ void main() {
|
||||
expect(parsed.darkMode, isTrue);
|
||||
expect(parsed.products.single['name'], 'Milk');
|
||||
expect(parsed.shops.single['id'], 8);
|
||||
expect(parsed.shops.single['name'], 'Weekly shop');
|
||||
expect(parsed.shopItems.single['product_id'], 1);
|
||||
expect(parsed.shopTags.single['tag'], 'weekly');
|
||||
expect(parsed.shoppingLists.single['name'], 'Weekly');
|
||||
expect(parsed.shoppingListItems.single['name'], 'Milk');
|
||||
expect(parsed.images['products/product_1.jpg'], 'abc123');
|
||||
@@ -95,6 +101,7 @@ void main() {
|
||||
expect(parsed.version, 1);
|
||||
expect(parsed.shoppingLists, isEmpty);
|
||||
expect(parsed.shoppingListItems, isEmpty);
|
||||
expect(parsed.shopTags, isEmpty);
|
||||
});
|
||||
|
||||
test('rejects a file that is not a Receipity backup', () {
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:receipity/models/shop.dart';
|
||||
import 'package:receipity/utils/shop_calendar.dart';
|
||||
import 'package:receipity/utils/shop_log_filter.dart';
|
||||
|
||||
Shop _shop({
|
||||
required int id,
|
||||
required DateTime at,
|
||||
String supermarket = 'Jumbo',
|
||||
String? name,
|
||||
List<String> tags = const [],
|
||||
}) {
|
||||
return Shop(
|
||||
id: id,
|
||||
supermarket: supermarket,
|
||||
name: name,
|
||||
shoppedAt: at,
|
||||
total: 10,
|
||||
itemCount: 1,
|
||||
tags: tags,
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('monthGrid', () {
|
||||
test('pads August 2026 from Saturday with Monday-first weeks', () {
|
||||
final cells = monthGrid(DateTime(2026, 8));
|
||||
expect(cells.length % 7, 0);
|
||||
expect(cells[0], isNull);
|
||||
expect(cells[1], isNull);
|
||||
expect(cells[2], isNull);
|
||||
expect(cells[3], isNull);
|
||||
expect(cells[4], isNull);
|
||||
expect(cells[5], DateTime(2026, 8, 1));
|
||||
expect(cells[35], DateTime(2026, 8, 31));
|
||||
expect(cells.last, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
test('tripCountsByDay groups multiple trips on the same day', () {
|
||||
final counts = tripCountsByDay([
|
||||
DateTime(2026, 8, 12, 9),
|
||||
DateTime(2026, 8, 12, 18),
|
||||
DateTime(2026, 8, 13),
|
||||
]);
|
||||
expect(counts[DateTime(2026, 8, 12)], 2);
|
||||
expect(counts[DateTime(2026, 8, 13)], 1);
|
||||
expect(heatmapLevel(0), 0);
|
||||
expect(heatmapLevel(1), 1);
|
||||
expect(heatmapLevel(4), 4);
|
||||
expect(heatmapLevel(9), 4);
|
||||
});
|
||||
|
||||
group('filterShops', () {
|
||||
final shops = [
|
||||
_shop(id: 1, at: DateTime(2026, 8, 12), tags: const ['weekly']),
|
||||
_shop(
|
||||
id: 2,
|
||||
at: DateTime(2026, 8, 13),
|
||||
name: 'Work lunch',
|
||||
tags: const ['work'],
|
||||
),
|
||||
];
|
||||
const names = {
|
||||
1: ['Milk', 'Bread'],
|
||||
2: ['Coffee'],
|
||||
};
|
||||
|
||||
test('filters by product name', () {
|
||||
final found = filterShops(
|
||||
shops: shops,
|
||||
productNames: names,
|
||||
query: 'milk',
|
||||
);
|
||||
expect(found.map((shop) => shop.id), [1]);
|
||||
});
|
||||
|
||||
test('filters by selected day', () {
|
||||
final found = filterShops(
|
||||
shops: shops,
|
||||
productNames: names,
|
||||
selectedDay: DateTime(2026, 8, 13),
|
||||
);
|
||||
expect(found.single.id, 2);
|
||||
});
|
||||
|
||||
test('filters by tag', () {
|
||||
final found = filterShops(
|
||||
shops: shops,
|
||||
productNames: names,
|
||||
tag: 'weekly',
|
||||
);
|
||||
expect(found.single.id, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
+35
-1
@@ -4,6 +4,7 @@ import 'package:receipity/main.dart';
|
||||
import 'package:receipity/models/line_item.dart';
|
||||
import 'package:receipity/review_screen.dart';
|
||||
import 'package:receipity/services/product_repository.dart';
|
||||
import 'package:receipity/widgets/shop_heatmap.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('scan screen shows capture actions and bottom navigation', (
|
||||
@@ -22,10 +23,41 @@ void main() {
|
||||
);
|
||||
expect(find.text('Products'), findsOneWidget);
|
||||
expect(find.text('Lists'), findsOneWidget);
|
||||
expect(find.text('Add'), findsOneWidget);
|
||||
expect(find.byTooltip('Add'), findsOneWidget);
|
||||
expect(find.byIcon(Icons.add), findsOneWidget);
|
||||
expect(find.text('Shop log'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shop log has product search', (tester) async {
|
||||
await tester.pumpWidget(ReceipityApp());
|
||||
await tester.tap(find.text('Shop log'));
|
||||
await tester.pump();
|
||||
expect(find.byTooltip('Search products'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shop heatmap renders the visible month', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: ShopHeatmap(
|
||||
month: DateTime(2026, 8),
|
||||
counts: const {},
|
||||
monthTotal: 0,
|
||||
monthTripCount: 0,
|
||||
canGoForward: false,
|
||||
onPreviousMonth: () {},
|
||||
onNextMonth: () {},
|
||||
onSelectDay: (_) {},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.text('August 2026'), findsOneWidget);
|
||||
expect(find.text('No trips this month'), findsOneWidget);
|
||||
expect(find.text('Less'), findsOneWidget);
|
||||
expect(find.text('More'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('enter manually opens a blank trip', (tester) async {
|
||||
await tester.pumpWidget(ReceipityApp());
|
||||
await tester.tap(find.text('Enter manually'));
|
||||
@@ -60,6 +92,8 @@ void main() {
|
||||
expect(find.text('Add item'), findsOneWidget);
|
||||
expect(find.textContaining('Save trip'), findsOneWidget);
|
||||
expect(find.text('Supermarket'), findsOneWidget);
|
||||
expect(find.text('Trip name'), findsOneWidget);
|
||||
expect(find.text('Add tag'), findsOneWidget);
|
||||
|
||||
await tester.drag(find.text('Milk'), const Offset(-500, 0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
Reference in New Issue
Block a user