Files
ReelShort/test/config/brand_identity_test.dart
T

138 lines
4.8 KiB
Dart

// Author: fruit.com.cn
// 验证品牌名称、原生启动布局与平台图标资源。
import 'dart:convert';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/l10n/app_localizations.dart';
const _iconAsset = 'assets/icon/ymb.png';
const _iconSize = 1024;
const _launchWidth = 390;
const _launchHeight = 844;
const _androidRoot = 'android/app/src/main/res';
const _iosRoot = 'ios/Runner/Assets.xcassets';
const _ink = [0, 0, 0, 255];
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
test('should_use_ymb_when_resolving_each_app_locale', () async {
for (final locale in AppLocalizations.supportedLocales) {
final l10n = await AppLocalizations.delegate.load(locale);
expect(l10n.appName, 'ymb');
}
});
test('should_keep_reference_colors_when_decoding_master_icon', () async {
final image = await _decode(_iconAsset);
addTearDown(image.dispose);
expect(image.width, _iconSize);
expect(image.height, _iconSize);
final bytes = await image.toByteData();
final pixel = bytes!.buffer.asUint8List().sublist(0, _ink.length);
for (var channel = 0; channel < _ink.length; channel++) {
expect(pixel[channel], closeTo(_ink[channel], 2));
}
});
test('should_match_declared_sizes_when_loading_ios_app_icons', () async {
final manifest =
jsonDecode(
File(
'$_iosRoot/AppIcon.appiconset/Contents.json',
).readAsStringSync(),
)
as Map<String, dynamic>;
for (final entry in manifest['images'] as List) {
final size = double.parse((entry['size'] as String).split('x').first);
final scale = int.parse((entry['scale'] as String).replaceAll('x', ''));
final image = await _decode(
'$_iosRoot/AppIcon.appiconset/${entry['filename']}',
);
expect(image.width, (size * scale).round());
expect(image.height, image.width);
image.dispose();
}
});
test('should_fit_full_reference_when_loading_ios_launch_screen', () {
final storyboard = File(
'ios/Runner/Base.lproj/LaunchScreen.storyboard',
).readAsStringSync();
expect(storyboard, contains('contentMode="scaleAspectFit"'));
expect(storyboard, contains('firstAttribute="leading"'));
expect(storyboard, contains('firstAttribute="trailing"'));
});
test('should_keep_reference_ratio_when_loading_ios_launch_images', () async {
for (var scale = 1; scale <= 3; scale++) {
final suffix = scale == 1 ? '' : '@${scale}x';
final image = await _decode(
'$_iosRoot/LaunchImage.imageset/LaunchImage$suffix.png',
);
expect(image.width, _launchWidth * scale);
expect(image.height, _launchHeight * scale);
image.dispose();
}
});
test('should_keep_reference_tint_when_loading_android_launch_layers', () {
for (final qualifier in ['', '-v21', '-v31', '-night', '-night-v21']) {
final layers = File(
'$_androidRoot/drawable$qualifier/launch_background.xml',
).readAsStringSync();
expect(layers, contains('@color/splash_background'));
expect(layers, isNot(contains('<gradient')));
expect(layers, contains('android:gravity="center"'));
expect(layers, contains('@drawable/splash_screen'));
}
});
test('should_preserve_safe_area_when_loading_android12_mark', () async {
const root = '$_androidRoot/drawable-xxxhdpi';
final image = await _decode('$root/android12splash.png');
addTearDown(image.dispose);
const canvasSize = 1152;
const markInset = 416;
const center = canvasSize ~/ 2;
expect(image.width, canvasSize);
expect(image.height, canvasSize);
final data = (await image.toByteData())!.buffer.asUint8List();
int alphaAt(int x, int y) => data[(y * canvasSize + x) * 4 + 3];
expect(alphaAt(0, 0), 0);
expect(alphaAt(markInset - 1, center), 0);
expect(alphaAt(markInset + 1, center), 255);
expect(alphaAt(center, center), 255);
for (final qualifier in ['', '-night']) {
final styles = File(
'$_androidRoot/values$qualifier-v31/styles.xml',
).readAsStringSync();
expect(styles, contains('@drawable/android12splash'));
}
});
test('should_use_ymb_when_resolving_platform_display_names', () {
final manifest = File(
'android/app/src/main/AndroidManifest.xml',
).readAsStringSync();
expect(manifest, contains('android:label="ymb"'));
final plist = File('ios/Runner/Info.plist').readAsStringSync();
expect(
RegExp(
r'<key>CFBundleDisplayName</key>\s*<string>ymb</string>',
).hasMatch(plist),
isTrue,
);
});
}
Future<ui.Image> _decode(String path) async {
final codec = await ui.instantiateImageCodec(File(path).readAsBytesSync());
final frame = await codec.getNextFrame();
codec.dispose();
return frame.image;
}