import 'package:commons_core/commons_core.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tane/data/species_catalog.dart'; import 'package:tane/data/species_repository.dart'; import 'package:tane/db/database.dart'; import '../support/test_support.dart'; const _seeds = [ SpeciesSeed( scientificName: 'Solanum lycopersicum', family: 'Solanaceae', commonNames: { 'en': ['Tomato'], 'es': ['Tomate'], }, ), SpeciesSeed( scientificName: 'Phaseolus vulgaris', family: 'Fabaceae', commonNames: { 'en': ['Common bean'], 'es': ['Judía', 'Alubia'], }, ), ]; void main() { late AppDatabase db; late SpeciesRepository repo; setUp(() { db = newTestDatabase(); repo = SpeciesRepository(db, idGen: IdGen()); }); tearDown(() => db.close()); test( 'parseSpeciesCatalog reads scientific name, family and common names', () { const json = ''' {"version":3,"species":[ {"scientific_name":"Zea mays","family":"Poaceae","wikidata_qid":"Q11575","gbif_key":2703077,"common":{"en":["Maize"],"es":["Maíz"]}} ]}'''; final seeds = parseSpeciesCatalog(json); expect(seeds.single.scientificName, 'Zea mays'); expect(seeds.single.family, 'Poaceae'); expect(seeds.single.wikidataQid, 'Q11575'); expect(seeds.single.gbifKey, 2703077); expect(seeds.single.commonNames['es'], ['Maíz']); }, ); test('seedBundled inserts species and is idempotent', () async { await repo.seedBundled(_seeds); await repo.seedBundled(_seeds); // second run must not duplicate final species = await db.select(db.species).get(); expect(species.length, 2); expect(species.every((s) => s.isBundled), isTrue); }); test('search matches by scientific name', () async { await repo.seedBundled(_seeds); final results = await repo.search('phaseolus'); expect(results.single.scientificName, 'Phaseolus vulgaris'); }); test('search matches by common name and returns a localized label', () async { await repo.seedBundled(_seeds); final es = await repo.search('alubia', languageCode: 'es'); expect(es.single.scientificName, 'Phaseolus vulgaris'); expect(es.single.commonName, anyOf('Judía', 'Alubia')); final en = await repo.search('tom', languageCode: 'en'); expect(en.single.commonName, 'Tomato'); expect(en.single.displayLabel, 'Tomato (Solanum lycopersicum)'); }); test('empty query returns nothing', () async { await repo.seedBundled(_seeds); expect(await repo.search(' '), isEmpty); }); test('seedBundled stores wikidata id and gbif key', () async { await repo.seedBundled(const [ SpeciesSeed( scientificName: 'Solanum lycopersicum', family: 'Solanaceae', wikidataQid: 'Q13223', gbifKey: 2930137, commonNames: { 'en': ['Tomato'], }, ), ]); final row = await db.select(db.species).getSingle(); expect(row.wikidataQid, 'Q13223'); expect(row.gbifKey, 2930137); }); test('seedBundled backfills reference fields added later', () async { // First seed lacks the enrichment fields (an older catalog). await repo.seedBundled(const [ SpeciesSeed( scientificName: 'Allium cepa', commonNames: { 'en': ['Onion'], }, ), ]); // A later catalog carries them; identity is preserved, fields are filled. await repo.seedBundled(const [ SpeciesSeed( scientificName: 'Allium cepa', wikidataQid: 'Q23485', gbifKey: 2857697, viabilityYears: 1, commonNames: { 'en': ['Onion'], }, ), ]); final rows = await db.select(db.species).get(); expect(rows.length, 1); expect(rows.single.wikidataQid, 'Q23485'); expect(rows.single.gbifKey, 2857697); expect(rows.single.viabilityYears, 1); }); test('search matches a non-Latin common name', () async { await repo.seedBundled(const [ SpeciesSeed( scientificName: 'Solanum lycopersicum', commonNames: { 'ar': ['طماطم'], 'zh': ['番茄'], }, ), ]); final ar = await repo.search('طماطم', languageCode: 'ar'); expect(ar.single.scientificName, 'Solanum lycopersicum'); expect(ar.single.commonName, 'طماطم'); final zh = await repo.search('番茄', languageCode: 'zh'); expect(zh.single.commonName, '番茄'); }); test('search respects the limit', () async { final many = [ for (var i = 0; i < 20; i++) SpeciesSeed( scientificName: 'Genus species$i', commonNames: const { 'en': ['Plant'], }, ), ]; await repo.seedBundled(many); final results = await repo.search('Genus', limit: 5); expect(results.length, 5); }); }