import 'dart:convert';
import 'dart:io';
import 'package:consumer_app/l10n/app_localizations.dart';
import 'package:consumer_app/l10n/backend_localizations.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('locale files do not contain duplicate top-level keys', () {
final keyPattern = RegExp(r'^ "([A-Za-z0-9_]+)"\s*:');
for (final path in ['lib/l10n/app_de.arb', 'lib/l10n/app_en.arb']) {
final keys = keyPattern
.allMatches(File(path).readAsStringSync())
.map((match) => match.group(1)!)
.toList(growable: false);
expect(
keys.toSet().length,
keys.length,
reason: '$path must not redefine a top-level locale key',
);
}
});
test('German and English locale files expose the same keys', () {
final german =
jsonDecode(File('lib/l10n/app_de.arb').readAsStringSync())
as Map<String, dynamic>;
final english =
jsonDecode(File('lib/l10n/app_en.arb').readAsStringSync())
as Map<String, dynamic>;
final germanKeys = german.keys.where((key) => !key.startsWith('@')).toSet();
final englishKeys = english.keys
.where((key) => !key.startsWith('@'))
.toSet();
expect(germanKeys, englishKeys);
});
test('locale files do not contain empty user-facing values', () {
for (final path in ['lib/l10n/app_de.arb', 'lib/l10n/app_en.arb']) {
final values =
jsonDecode(File(path).readAsStringSync()) as Map<String, dynamic>;
for (final entry in values.entries) {
if (entry.key.startsWith('@') || entry.key == '@@locale') continue;
expect(
entry.value,
isA<String>(),
reason: '${entry.key} in $path must be a localized string',
);
expect(
(entry.value as String).trim(),
isNotEmpty,
reason: '${entry.key} in $path must not be empty',
);
}
}
});
test('backend text wrapper preserves discovery filter fallbacks', () async {
final base = await AppLocalizations.delegate.load(const Locale('de'));
final localized = BackendAppLocalizations(base: base, overrides: const {});
expect(localized.filterAll, 'Alle');
expect(localized.filterMinimum, 'Von');
expect(localized.filterMaximum, 'Bis');
expect(localized.filterLabel, 'Filter');
});
test(
'backend text wrapper preserves Places and Events filter fallbacks',
() async {
final base = await AppLocalizations.delegate.load(const Locale('de'));
final localized = BackendAppLocalizations(
base: base,
overrides: const {},
);
expect(localized.placesFilterApply, 'Orte anzeigen');
expect(localized.placeCategoryGastronomy, 'Gastronomie');
expect(localized.eventDateWeekend, 'Dieses Wochenende');
expect(localized.eventFilterApply, 'Events anzeigen');
},
);
test('backend text wrapper forwards location and current listing getters',
() async {
final base = await AppLocalizations.delegate.load(const Locale('de'));
final localized = BackendAppLocalizations(
base: base,
overrides: const {},
);
expect(localized.locationStartupTitle, 'Standort für lokale Entdeckungen');
expect(localized.locationStartupBody, contains('Koordinaten'));
expect(localized.locationActive, 'Standort aktiv');
expect(
localized.detailHeatingCostsIncluded,
'Heizkosten in Nebenkosten enthalten',
);
expect(localized.listingValueMoreThanSix, 'Mehr als 6');
expect(localized.listingValueCustom, 'Eigene Anzahl');
});
}
