test(state): cover InventoryCubit and VarietyDetailCubit; refresh block1 status doc
This commit is contained in:
parent
a96d82add9
commit
cf5d302cc1
4 changed files with 292 additions and 47 deletions
134
apps/app_seeds/test/state/inventory_cubit_test.dart
Normal file
134
apps/app_seeds/test/state/inventory_cubit_test.dart
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tane/data/variety_repository.dart';
|
||||
import 'package:tane/db/database.dart';
|
||||
import 'package:tane/db/enums.dart';
|
||||
import 'package:tane/state/inventory_cubit.dart';
|
||||
|
||||
import '../support/test_support.dart';
|
||||
|
||||
/// Waits until the cubit's state satisfies [predicate], whether it already
|
||||
/// does or a later stream emission gets it there.
|
||||
Future<InventoryState> waitFor(
|
||||
InventoryCubit cubit,
|
||||
bool Function(InventoryState) predicate,
|
||||
) async {
|
||||
if (predicate(cubit.state)) return cubit.state;
|
||||
return cubit.stream.firstWhere(predicate).timeout(const Duration(seconds: 5));
|
||||
}
|
||||
|
||||
void main() {
|
||||
late AppDatabase db;
|
||||
late VarietyRepository repo;
|
||||
late InventoryCubit cubit;
|
||||
|
||||
setUp(() {
|
||||
db = newTestDatabase();
|
||||
repo = newTestRepository(db);
|
||||
cubit = InventoryCubit(repo);
|
||||
});
|
||||
tearDown(() async {
|
||||
await cubit.close();
|
||||
await db.close();
|
||||
});
|
||||
|
||||
test('subscribes to the inventory and leaves loading', () async {
|
||||
await repo.addQuickVariety(label: 'Maize');
|
||||
final state = await waitFor(cubit, (s) => !s.loading && s.items.isNotEmpty);
|
||||
expect(state.items.single.label, 'Maize');
|
||||
});
|
||||
|
||||
test('drafts stay in the tray and never mix into the list', () async {
|
||||
await repo.addDraftVariety(Uint8List.fromList([1, 2, 3]));
|
||||
var state = await waitFor(cubit, (s) => s.drafts.isNotEmpty);
|
||||
expect(state.items, isEmpty);
|
||||
|
||||
// Naming the draft promotes it: tray empties, list gains the item.
|
||||
await repo.nameDraft(state.drafts.single.id, 'Named at last');
|
||||
state = await waitFor(cubit, (s) => s.items.isNotEmpty && s.drafts.isEmpty);
|
||||
expect(state.items.single.label, 'Named at last');
|
||||
});
|
||||
|
||||
test('search narrows visibleItems by label, case-insensitively', () async {
|
||||
await repo.addQuickVariety(label: 'Tomate rosa');
|
||||
await repo.addQuickVariety(label: 'Lechuga');
|
||||
await waitFor(cubit, (s) => s.items.length == 2);
|
||||
|
||||
cubit.search('TOMA');
|
||||
expect(cubit.state.visibleItems.single.label, 'Tomate rosa');
|
||||
|
||||
cubit.search('');
|
||||
expect(cubit.state.visibleItems, hasLength(2));
|
||||
});
|
||||
|
||||
test('toggleCategory adds then removes the filter', () async {
|
||||
await repo.addQuickVariety(label: 'Maize', category: 'Poaceae');
|
||||
await repo.addQuickVariety(label: 'Bean', category: 'Fabaceae');
|
||||
await waitFor(cubit, (s) => s.items.length == 2);
|
||||
|
||||
cubit.toggleCategory('Poaceae');
|
||||
expect(cubit.state.visibleItems.single.label, 'Maize');
|
||||
|
||||
cubit.toggleCategory('Poaceae');
|
||||
expect(cubit.state.visibleItems, hasLength(2));
|
||||
});
|
||||
|
||||
test('toggleType keeps only varieties holding a lot of that form', () async {
|
||||
final seedId = await repo.addQuickVariety(label: 'Seedy');
|
||||
await repo.addLot(varietyId: seedId, type: LotType.seed);
|
||||
final plantId = await repo.addQuickVariety(label: 'Planty');
|
||||
await repo.addLot(varietyId: plantId, type: LotType.plant);
|
||||
await waitFor(
|
||||
cubit,
|
||||
(s) => s.items.length == 2 && s.items.every((i) => i.lotTypes.isNotEmpty),
|
||||
);
|
||||
|
||||
cubit.toggleType(LotType.plant);
|
||||
expect(cubit.state.visibleItems.single.label, 'Planty');
|
||||
});
|
||||
|
||||
test('organic and needs-reproduction filters', () async {
|
||||
final ecoId = await repo.addQuickVariety(label: 'Eco');
|
||||
await repo.updateVariety(id: ecoId, isOrganic: true);
|
||||
final tiredId = await repo.addQuickVariety(label: 'Tired');
|
||||
await repo.updateVariety(id: tiredId, needsReproduction: true);
|
||||
await waitFor(cubit, (s) => s.hasOrganic && s.hasNeedsReproduction);
|
||||
|
||||
cubit.toggleOrganicOnly();
|
||||
expect(cubit.state.visibleItems.single.label, 'Eco');
|
||||
cubit.toggleOrganicOnly();
|
||||
|
||||
cubit.toggleNeedsReproductionOnly();
|
||||
expect(cubit.state.visibleItems.single.label, 'Tired');
|
||||
});
|
||||
|
||||
test('clearFilters resets every filter but keeps the search query', () async {
|
||||
await repo.addQuickVariety(label: 'Maize', category: 'Poaceae');
|
||||
await waitFor(cubit, (s) => s.items.isNotEmpty);
|
||||
|
||||
cubit
|
||||
..search('mai')
|
||||
..toggleCategory('Poaceae')
|
||||
..toggleType(LotType.seed)
|
||||
..toggleOrganicOnly()
|
||||
..toggleNeedsReproductionOnly();
|
||||
cubit.clearFilters();
|
||||
|
||||
expect(cubit.state.categoryFilter, isEmpty);
|
||||
expect(cubit.state.typeFilter, isEmpty);
|
||||
expect(cubit.state.organicOnly, isFalse);
|
||||
expect(cubit.state.needsReproductionOnly, isFalse);
|
||||
expect(cubit.state.query, 'mai');
|
||||
});
|
||||
|
||||
test('categories dedupes and preserves first-seen order', () async {
|
||||
await repo.addQuickVariety(label: 'A', category: 'Poaceae');
|
||||
await repo.addQuickVariety(label: 'B', category: 'Fabaceae');
|
||||
await repo.addQuickVariety(label: 'C', category: 'Poaceae');
|
||||
final state = await waitFor(cubit, (s) => s.items.length == 3);
|
||||
|
||||
expect(state.categories, hasLength(2));
|
||||
expect(state.categories.toSet(), {'Poaceae', 'Fabaceae'});
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue