98 lines
3.8 KiB
Dart
98 lines
3.8 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:drift/native.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:mews/application/controllers/reader_settings_controller.dart';
|
|
import 'package:mews/application/fonts.dart';
|
|
import 'package:mews/database/database.dart';
|
|
|
|
/// The families pubspec.yaml declares, with the asset paths of each.
|
|
Map<String, List<String>> _declaredFonts() {
|
|
final lines = File('pubspec.yaml').readAsLinesSync();
|
|
final declared = <String, List<String>>{};
|
|
String? family;
|
|
for (final line in lines) {
|
|
final name = RegExp(r'^ - family: (.+)$').firstMatch(line);
|
|
if (name != null) {
|
|
family = name.group(1)!.trim();
|
|
declared[family] = [];
|
|
continue;
|
|
}
|
|
final asset = RegExp(r'^ - asset: (.+)$').firstMatch(line);
|
|
if (asset != null && family != null) {
|
|
declared[family]!.add(asset.group(1)!.trim());
|
|
}
|
|
}
|
|
return declared;
|
|
}
|
|
|
|
void main() {
|
|
test('every offered typeface is bundled under the name it is stored by', () {
|
|
final declared = _declaredFonts();
|
|
for (final font in readerFonts) {
|
|
// A family named here but not in pubspec renders in the platform's font
|
|
// instead, silently: the reader would pick it and see no change.
|
|
expect(declared, contains(font.family),
|
|
reason: '${font.family} is offered but not declared in pubspec.yaml');
|
|
expect(declared[font.family], hasLength(4),
|
|
reason: '${font.family} needs regular, italic, bold and bold italic');
|
|
for (final asset in declared[font.family]!) {
|
|
expect(File(asset).existsSync(), isTrue, reason: '$asset is missing');
|
|
}
|
|
}
|
|
});
|
|
|
|
test('a fallback only names a typeface that is bundled', () {
|
|
final declared = _declaredFonts();
|
|
for (final font in readerFonts) {
|
|
for (final family in font.fallback) {
|
|
// A fallback naming a family the build does not carry is silently
|
|
// skipped, so the glyph would come from the platform after all.
|
|
expect(declared, contains(family),
|
|
reason: '${font.family} falls back to an absent $family');
|
|
expect(family, isNot(font.family), reason: 'falls back to itself');
|
|
for (final asset in declared[family]!) {
|
|
expect(File(asset).existsSync(), isTrue, reason: '$asset is missing');
|
|
}
|
|
}
|
|
}
|
|
expect(readerFonts.map((f) => f.family), contains(defaultFontFamily));
|
|
expect(fallbackFor('Comic Sans MS'), isEmpty);
|
|
});
|
|
|
|
test('every typeface can reach Hebrew without the platform', () {
|
|
// Hebrew ships from the start, so it must never depend on what the device
|
|
// happens to have installed.
|
|
for (final font in readerFonts) {
|
|
expect(font.fallback, anyElement(anyOf(hebrewSans, hebrewSerif)),
|
|
reason: '${font.family} has no Hebrew to fall back on');
|
|
}
|
|
});
|
|
|
|
test('every typeface has a label of its own', () {
|
|
final ftl = File('locales/en-US/main.ftl').readAsStringSync();
|
|
final ids = <String>{};
|
|
for (final font in readerFonts) {
|
|
expect(ftl, contains('${font.labelId} ='),
|
|
reason: '${font.family} has no label');
|
|
expect(ids.add(font.labelId), isTrue, reason: 'duplicate label id');
|
|
}
|
|
});
|
|
|
|
test('a typeface this build does not ship is refused', () async {
|
|
final db = MewsDatabase.test(NativeDatabase.memory());
|
|
addTearDown(db.close);
|
|
final settings = ReaderSettingsController(db);
|
|
|
|
expect(await settings.setFont('Literata'), isTrue);
|
|
expect(settings.font.value, 'Literata');
|
|
|
|
// Comic Sans is not bundled; accepting it would render in the platform
|
|
// font while the settings page claimed otherwise.
|
|
expect(await settings.setFont('Comic Sans MS'), isFalse);
|
|
expect(settings.font.value, 'Literata');
|
|
expect(await settings.setFont(''), isFalse);
|
|
expect(settings.font.value, 'Literata');
|
|
});
|
|
}
|