style: dart format reflow (no behavior change)
This commit is contained in:
parent
cf5d302cc1
commit
e3ec855630
17 changed files with 197 additions and 139 deletions
|
|
@ -18,35 +18,39 @@ void main() {
|
|||
|
||||
Uint8List photo(int seed) => Uint8List.fromList([seed, seed, seed]);
|
||||
|
||||
test('a captured draft is hidden from the list but shown in the tray',
|
||||
() async {
|
||||
final id = await repo.addDraftVariety(photo(1));
|
||||
test(
|
||||
'a captured draft is hidden from the list but shown in the tray',
|
||||
() async {
|
||||
final id = await repo.addDraftVariety(photo(1));
|
||||
|
||||
// Not in the main inventory…
|
||||
expect(await repo.watchInventory().first, isEmpty);
|
||||
// Not in the main inventory…
|
||||
expect(await repo.watchInventory().first, isEmpty);
|
||||
|
||||
// …but in the "to catalogue" tray, with its photo and no name yet.
|
||||
final drafts = await repo.watchDrafts().first;
|
||||
expect(drafts, hasLength(1));
|
||||
expect(drafts.single.id, id);
|
||||
expect(drafts.single.isDraft, isTrue);
|
||||
expect(drafts.single.label, '');
|
||||
expect(drafts.single.photo, isNotNull);
|
||||
});
|
||||
// …but in the "to catalogue" tray, with its photo and no name yet.
|
||||
final drafts = await repo.watchDrafts().first;
|
||||
expect(drafts, hasLength(1));
|
||||
expect(drafts.single.id, id);
|
||||
expect(drafts.single.isDraft, isTrue);
|
||||
expect(drafts.single.label, '');
|
||||
expect(drafts.single.photo, isNotNull);
|
||||
},
|
||||
);
|
||||
|
||||
test('naming a draft promotes it into the list and out of the tray',
|
||||
() async {
|
||||
final id = await repo.addDraftVariety(photo(2));
|
||||
await repo.nameDraft(id, 'Grandma tomato');
|
||||
test(
|
||||
'naming a draft promotes it into the list and out of the tray',
|
||||
() async {
|
||||
final id = await repo.addDraftVariety(photo(2));
|
||||
await repo.nameDraft(id, 'Grandma tomato');
|
||||
|
||||
expect(await repo.watchDrafts().first, isEmpty);
|
||||
final list = await repo.watchInventory().first;
|
||||
expect(list.single.id, id);
|
||||
expect(list.single.label, 'Grandma tomato');
|
||||
expect(list.single.isDraft, isFalse);
|
||||
// The captured photo survived the promotion.
|
||||
expect(list.single.photo, isNotNull);
|
||||
});
|
||||
expect(await repo.watchDrafts().first, isEmpty);
|
||||
final list = await repo.watchInventory().first;
|
||||
expect(list.single.id, id);
|
||||
expect(list.single.label, 'Grandma tomato');
|
||||
expect(list.single.isDraft, isFalse);
|
||||
// The captured photo survived the promotion.
|
||||
expect(list.single.photo, isNotNull);
|
||||
},
|
||||
);
|
||||
|
||||
test('the tray is ordered newest-capture first', () async {
|
||||
final first = await repo.addDraftVariety(photo(1));
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ void main() {
|
|||
await newTestSpeciesRepository(db).seedBundled(const [tomato]);
|
||||
final repo = newTestRepository(db);
|
||||
|
||||
const csv = 'variety_label,category,species_scientific_name,'
|
||||
const csv =
|
||||
'variety_label,category,species_scientific_name,'
|
||||
'cultivar_name,lot_type,harvest_year,quantity_kind,quantity_precise\r\n'
|
||||
'Grandma tomato,Solanaceae,Solanum lycopersicum,Marmande,seed,2024,cob,3\r\n';
|
||||
final summary = await repo.importCsv(codec.decode(csv));
|
||||
|
|
@ -44,7 +45,8 @@ void main() {
|
|||
|
||||
test('an unmatched species name leaves speciesId null', () async {
|
||||
final repo = newTestRepository(db); // no bundled catalog
|
||||
const csv = 'variety_label,species_scientific_name\r\n'
|
||||
const csv =
|
||||
'variety_label,species_scientific_name\r\n'
|
||||
'Mystery bean,Phaseolus nonexistus\r\n';
|
||||
await repo.importCsv(codec.decode(csv));
|
||||
final variety = await db.select(db.varieties).getSingle();
|
||||
|
|
@ -60,19 +62,26 @@ void main() {
|
|||
expect(varieties, hasLength(2));
|
||||
});
|
||||
|
||||
test('stores vernacular names and links attached to the new variety', () async {
|
||||
final repo = newTestRepository(db);
|
||||
const csv = 'variety_label,vernacular_names,external_links\r\n'
|
||||
'Tomato,"tomate (es); granny tomato","Wiki|https://example.org"\r\n';
|
||||
await repo.importCsv(codec.decode(csv));
|
||||
test(
|
||||
'stores vernacular names and links attached to the new variety',
|
||||
() async {
|
||||
final repo = newTestRepository(db);
|
||||
const csv =
|
||||
'variety_label,vernacular_names,external_links\r\n'
|
||||
'Tomato,"tomate (es); granny tomato","Wiki|https://example.org"\r\n';
|
||||
await repo.importCsv(codec.decode(csv));
|
||||
|
||||
final variety = await db.select(db.varieties).getSingle();
|
||||
final names = await db.select(db.varietyVernacularNames).get();
|
||||
expect(names.map((n) => n.name), containsAll(['tomate', 'granny tomato']));
|
||||
expect(names.every((n) => n.varietyId == variety.id), isTrue);
|
||||
final variety = await db.select(db.varieties).getSingle();
|
||||
final names = await db.select(db.varietyVernacularNames).get();
|
||||
expect(
|
||||
names.map((n) => n.name),
|
||||
containsAll(['tomate', 'granny tomato']),
|
||||
);
|
||||
expect(names.every((n) => n.varietyId == variety.id), isTrue);
|
||||
|
||||
final links = await db.select(db.externalLinks).get();
|
||||
expect(links.single.url, 'https://example.org');
|
||||
expect(links.single.parentId, variety.id);
|
||||
});
|
||||
final links = await db.select(db.externalLinks).get();
|
||||
expect(links.single.url, 'https://example.org');
|
||||
expect(links.single.parentId, variety.id);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,14 +50,16 @@ void main() {
|
|||
seedbankId: null,
|
||||
);
|
||||
|
||||
List<String> rowsOf(String csv) =>
|
||||
csv.trimRight().split('\r\n');
|
||||
List<String> rowsOf(String csv) => csv.trimRight().split('\r\n');
|
||||
|
||||
test('emits a header and one row per lot', () {
|
||||
final csv = codec.encode(
|
||||
InventorySnapshot(
|
||||
varieties: [variety()],
|
||||
lots: [lot(), lot(id: 'lot-2')],
|
||||
lots: [
|
||||
lot(),
|
||||
lot(id: 'lot-2'),
|
||||
],
|
||||
speciesNamesById: const {'sp-1': 'Solanum lycopersicum'},
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ void main() {
|
|||
});
|
||||
|
||||
test('skips rows without a variety_label', () {
|
||||
final csv = 'variety_label,category\r\n,Solanaceae\r\nTomato,Solanaceae\r\n';
|
||||
final csv =
|
||||
'variety_label,category\r\n,Solanaceae\r\nTomato,Solanaceae\r\n';
|
||||
final result = codec.decode(csv);
|
||||
expect(result.skippedRows, 1);
|
||||
expect(result.varieties, hasLength(1));
|
||||
|
|
@ -29,7 +30,8 @@ void main() {
|
|||
});
|
||||
|
||||
test('maps columns by header name regardless of order', () {
|
||||
final csv = 'category,variety_label,harvest_year,lot_type\r\n'
|
||||
final csv =
|
||||
'category,variety_label,harvest_year,lot_type\r\n'
|
||||
'Solanaceae,Tomato,2024,seed\r\n';
|
||||
final v = codec.decode(csv).varieties.single;
|
||||
expect(v.label, 'Tomato');
|
||||
|
|
@ -46,7 +48,8 @@ void main() {
|
|||
|
||||
test('unknown enums fall back: lot_type→seed, offer_status→private, '
|
||||
'quantity_kind dropped', () {
|
||||
final csv = 'variety_label,lot_type,offer_status,quantity_kind\r\n'
|
||||
final csv =
|
||||
'variety_label,lot_type,offer_status,quantity_kind\r\n'
|
||||
'Tomato,spaceship,gift,truckload\r\n';
|
||||
final lot = codec.decode(csv).varieties.single.lots.single;
|
||||
expect(lot.type, LotType.seed);
|
||||
|
|
@ -55,7 +58,8 @@ void main() {
|
|||
});
|
||||
|
||||
test('keeps a valid quantity_kind and parses precise/label', () {
|
||||
final csv = 'variety_label,quantity_kind,quantity_precise,quantity_label\r\n'
|
||||
final csv =
|
||||
'variety_label,quantity_kind,quantity_precise,quantity_label\r\n'
|
||||
'Maize,cob,3,a handful\r\n';
|
||||
final lot = codec.decode(csv).varieties.single.lots.single;
|
||||
expect(lot.quantityKind, 'cob');
|
||||
|
|
@ -63,16 +67,20 @@ void main() {
|
|||
expect(lot.quantityLabel, 'a handful');
|
||||
});
|
||||
|
||||
test('rows sharing a variety_id collapse into one variety with many lots', () {
|
||||
final csv = 'variety_id,variety_label,lot_type,harvest_year\r\n'
|
||||
'v1,Tomato,seed,2023\r\n'
|
||||
'v1,Tomato,seed,2024\r\n'
|
||||
'v2,Carrot,seed,2024\r\n';
|
||||
final result = codec.decode(csv);
|
||||
expect(result.varieties, hasLength(2));
|
||||
final tomato = result.varieties.firstWhere((v) => v.label == 'Tomato');
|
||||
expect(tomato.lots.map((l) => l.harvestYear), [2023, 2024]);
|
||||
});
|
||||
test(
|
||||
'rows sharing a variety_id collapse into one variety with many lots',
|
||||
() {
|
||||
final csv =
|
||||
'variety_id,variety_label,lot_type,harvest_year\r\n'
|
||||
'v1,Tomato,seed,2023\r\n'
|
||||
'v1,Tomato,seed,2024\r\n'
|
||||
'v2,Carrot,seed,2024\r\n';
|
||||
final result = codec.decode(csv);
|
||||
expect(result.varieties, hasLength(2));
|
||||
final tomato = result.varieties.firstWhere((v) => v.label == 'Tomato');
|
||||
expect(tomato.lots.map((l) => l.harvestYear), [2023, 2024]);
|
||||
},
|
||||
);
|
||||
|
||||
test('rows without a variety_id each become their own variety', () {
|
||||
final csv = 'variety_label,lot_type\r\nTomato,seed\r\nTomato,plant\r\n';
|
||||
|
|
@ -81,7 +89,8 @@ void main() {
|
|||
});
|
||||
|
||||
test('parses quoted fields with commas, doubled quotes and newlines', () {
|
||||
final csv = 'variety_label,variety_notes\r\n'
|
||||
final csv =
|
||||
'variety_label,variety_notes\r\n'
|
||||
'"Bean, ""the best""","line one\nline two"\r\n';
|
||||
final v = codec.decode(csv).varieties.single;
|
||||
expect(v.label, 'Bean, "the best"');
|
||||
|
|
@ -89,7 +98,8 @@ void main() {
|
|||
});
|
||||
|
||||
test('splits vernacular names and links back out', () {
|
||||
final csv = 'variety_label,vernacular_names,external_links\r\n'
|
||||
final csv =
|
||||
'variety_label,vernacular_names,external_links\r\n'
|
||||
'Tomato,"tomate (es); granny tomato","Wiki|https://example.org"\r\n';
|
||||
final v = codec.decode(csv).varieties.single;
|
||||
expect(v.vernacularNames.map((n) => n.name), ['tomate', 'granny tomato']);
|
||||
|
|
@ -152,7 +162,10 @@ void main() {
|
|||
final csv = codec.encode(
|
||||
InventorySnapshot(
|
||||
varieties: [variety()],
|
||||
lots: [lot(), lot(id: 'lot-2')],
|
||||
lots: [
|
||||
lot(),
|
||||
lot(id: 'lot-2'),
|
||||
],
|
||||
speciesNamesById: const {'sp-1': 'Solanum lycopersicum'},
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -170,7 +170,8 @@ void main() {
|
|||
test('unknown fields are ignored (forward compatibility, §5.2)', () {
|
||||
final root = jsonDecode(codec.encode(snapshot)) as Map<String, dynamic>;
|
||||
root['someFutureSection'] = {'x': 1};
|
||||
((root['varieties'] as List).single as Map<String, dynamic>)['futureField'] =
|
||||
((root['varieties'] as List).single
|
||||
as Map<String, dynamic>)['futureField'] =
|
||||
'ignored';
|
||||
final decoded = codec.decode(jsonEncode(root));
|
||||
expect(decoded.varieties, [variety]);
|
||||
|
|
|
|||
|
|
@ -114,8 +114,12 @@ void main() {
|
|||
final sourceRows = await source.exportInventory();
|
||||
final targetRows = await target.exportInventory();
|
||||
expect(
|
||||
targetRows.varieties.map((v) => v.copyWith(speciesId: const Value(null))),
|
||||
sourceRows.varieties.map((v) => v.copyWith(speciesId: const Value(null))),
|
||||
targetRows.varieties.map(
|
||||
(v) => v.copyWith(speciesId: const Value(null)),
|
||||
),
|
||||
sourceRows.varieties.map(
|
||||
(v) => v.copyWith(speciesId: const Value(null)),
|
||||
),
|
||||
);
|
||||
expect(targetRows.lots, sourceRows.lots);
|
||||
expect(targetRows.vernacularNames, sourceRows.vernacularNames);
|
||||
|
|
@ -130,9 +134,9 @@ void main() {
|
|||
expect(targetRows.varieties.single.speciesId, targetSpecies.id);
|
||||
|
||||
// Photo bytes and cover order survived.
|
||||
final detail = await target.watchVariety(
|
||||
targetRows.varieties.single.id,
|
||||
).first;
|
||||
final detail = await target
|
||||
.watchVariety(targetRows.varieties.single.id)
|
||||
.first;
|
||||
expect(detail!.photos.first.bytes, [40, 50, 60]);
|
||||
expect(detail.photos.last.bytes, [10, 20, 30]);
|
||||
},
|
||||
|
|
@ -229,10 +233,7 @@ void main() {
|
|||
final written = await (targetDb.select(
|
||||
targetDb.varieties,
|
||||
)..where((v) => v.label.equals('Written after import'))).getSingle();
|
||||
expect(
|
||||
Hlc.parse(written.updatedAt).compareTo(maxImported),
|
||||
greaterThan(0),
|
||||
);
|
||||
expect(Hlc.parse(written.updatedAt).compareTo(maxImported), greaterThan(0));
|
||||
});
|
||||
|
||||
test('unmatched species leaves speciesId null instead of dangling', () async {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue