feat(species): auto-classify variety species from its label
Infer the catalog species a free-text variety label names ("Maiz de la
abuela" -> Zea mays) and prefill the category from the species family.
- Pure, testable matcher (domain/species_autoclassify.dart): whole-word,
accent/case-insensitive, Unicode-aware (any script), longest-name-wins,
ambiguous names left unclassified, light plural fold.
- Quick-add and draft naming auto-link the species when the field is empty
(non-destructive; an explicit category is kept).
- Edit sheet offers a one-tap suggestion from the typed name.
Tests: matcher unit, repository integration, SpeciesRepository.classifyLabel,
and an edit-sheet widget test.
This commit is contained in:
parent
0e6ef13d00
commit
b840b83c42
15 changed files with 510 additions and 3 deletions
|
|
@ -76,6 +76,59 @@ void main() {
|
|||
await disposeTree(tester);
|
||||
});
|
||||
|
||||
testWidgets('typing a name suggests the species and links it on tap', (
|
||||
tester,
|
||||
) async {
|
||||
final species = newTestSpeciesRepository(db);
|
||||
await species.seedBundled(const [
|
||||
SpeciesSeed(
|
||||
scientificName: 'Zea mays',
|
||||
family: 'Poaceae',
|
||||
commonNames: {
|
||||
'en': ['Maize'],
|
||||
'es': ['Maíz'],
|
||||
},
|
||||
),
|
||||
]);
|
||||
final repo = newTestRepository(db);
|
||||
// A label that names no species yet, so nothing is auto-linked on create.
|
||||
final id = await repo.addQuickVariety(label: 'Grandma seed');
|
||||
|
||||
await tester.pumpWidget(
|
||||
wrapDetail(repository: repo, varietyId: id, species: species),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('detail.edit')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.enterText(
|
||||
find.byKey(const Key('editVariety.name')),
|
||||
'Maize criollo',
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// The suggestion surfaces from the typed name.
|
||||
final suggestion = find.byKey(const Key('editVariety.speciesSuggestion'));
|
||||
expect(suggestion, findsOneWidget);
|
||||
expect(find.text('Maize (Zea mays)'), findsOneWidget);
|
||||
|
||||
await tester.tap(suggestion);
|
||||
await tester.pumpAndSettle();
|
||||
// Picking fills the species field with the catalog label.
|
||||
expect(find.text('Maize (Zea mays)'), findsOneWidget);
|
||||
|
||||
final save = find.byKey(const Key('editVariety.save'));
|
||||
await tester.ensureVisible(save);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(save, warnIfMissed: false);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// The linked species now shows on the detail header (driven by the stream).
|
||||
expect(find.text('Zea mays'), findsOneWidget);
|
||||
await disposeTree(tester);
|
||||
});
|
||||
|
||||
testWidgets('adding a lot shows it in the list', (tester) async {
|
||||
final repo = newTestRepository(db);
|
||||
final id = await repo.addQuickVariety(label: 'Bean');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue