补充提交demo
This commit is contained in:
parent
4e64bc8196
commit
7bc09696af
|
|
@ -1,9 +1,9 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:yx_app_upgrade_flutter/app_upgrade_plugin.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:yx_app_upgrade_flutter/app_upgrade_plugin.dart';
|
||||
|
||||
void main() {
|
||||
// 确保Flutter绑定已初始化
|
||||
|
|
@ -50,13 +50,9 @@ class HomePage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
String _platformVersion = 'Unknown';
|
||||
final _appUpgradePlugin = AppUpgradePlugin();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initPlatformState();
|
||||
// Use addPostFrameCallback to ensure the context is valid and mounted
|
||||
// after the first frame has been rendered.
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
|
|
@ -70,46 +66,78 @@ class _HomePageState extends State<HomePage> {
|
|||
await AppUpgradeSimple.instance.checkUpdate(
|
||||
context: context,
|
||||
future: () async {
|
||||
// 模拟获取服务器版本信息
|
||||
// 实际使用时,您应该调用您的API,并返回 AppUpgradeVersion 对象
|
||||
// final response = await myApi.checkVersion();
|
||||
// return AppUpgradeVersion(...);
|
||||
final updateAppEvent = await _getUpdateAppEvent();
|
||||
print("获取最新版本: $updateAppEvent");
|
||||
if (updateAppEvent == null) return null;
|
||||
|
||||
// 这里为了演示,我们手动构造一个版本信息
|
||||
return AppUpgradeVersion(
|
||||
versionName: '1.0.1',
|
||||
versionBuildNumber: 11,
|
||||
isForce: true,
|
||||
updateContent: '修复了一些Bug\n优化了用户体验',
|
||||
downloadUrl: 'https://example.com/app.apk',
|
||||
supportedMethods: [AppUpgradeMethod.browser, AppUpgradeMethod.inApp, AppUpgradeMethod.market],
|
||||
);
|
||||
return _convertToAppUpgradeVersion(updateAppEvent);
|
||||
},
|
||||
showNoUpdateToast: false, // 禁用"已是最新版本"的提示
|
||||
autoInstall: true,
|
||||
onComplete: (bool val) {
|
||||
print("更新插件执行完成....: $val");
|
||||
},
|
||||
config: UpgradeConfig.development,
|
||||
// showNoUpdateToast: false,
|
||||
// autoDownload: false,
|
||||
// autoInstall: true,
|
||||
);
|
||||
debugPrint('=== 网络功能测试完成 ===');
|
||||
}
|
||||
|
||||
// Platform messages are asynchronous, so we initialize in an async method.
|
||||
Future<void> initPlatformState() async {
|
||||
String platformVersion;
|
||||
// Platform messages may fail, so we use a try/catch PlatformException.
|
||||
// We also handle the message potentially returning null.
|
||||
try {
|
||||
platformVersion = await _appUpgradePlugin.getPlatformVersion() ?? 'Unknown platform version';
|
||||
} on PlatformException {
|
||||
platformVersion = 'Failed to get platform version.';
|
||||
/// 获取最新版本
|
||||
Future<Map<String, dynamic>?> _getUpdateAppEvent() async {
|
||||
// 获取设备信息
|
||||
// String deviceInfo;
|
||||
/// 1:安卓,2:IOS
|
||||
int? deviceType = Platform.isAndroid
|
||||
? 1
|
||||
: Platform.isIOS
|
||||
? 2
|
||||
: null;
|
||||
if (deviceType == null) return null;
|
||||
|
||||
/// 支持更新内容 加粗、高亮、斜体、等
|
||||
return {
|
||||
"id": 708608950206533,
|
||||
"version": 307,
|
||||
"versionName": "1.0.9",
|
||||
"remark": """
|
||||
**布置工作:**上级可以向分属团队`布置任务`,设定类型和时间。\n
|
||||
**工作管理上:**__级可集中查看下级`所有工作`的详情与进度。__\n
|
||||
**学生详情:**__在[学生管理]中添加详情页,支持记录家长信息、学生备注等,完善学生档案。__\n""",
|
||||
"imageBase": null,
|
||||
"updatetype": 1,
|
||||
"isActive": 1,
|
||||
"fileid": 708608942190661,
|
||||
"fileName": "app-release(62).apk",
|
||||
"filePath": AppUpgradeVersion.getAppStoreByUrl('6747421483'),
|
||||
// "filePath":
|
||||
// "https://quanxue-oa.oss-cn-chengdu.aliyuncs.com/20251106/1762422545956.apk.1",
|
||||
"fileSize": 144214,
|
||||
"isforce": true
|
||||
};
|
||||
}
|
||||
|
||||
// If the widget was removed from the tree while the asynchronous platform
|
||||
// message was in flight, we want to discard the reply rather than calling
|
||||
// setState to update our non-existent appearance.
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
_platformVersion = platformVersion;
|
||||
});
|
||||
/// 将 UpdateappResult 转换为 AppUpgradeVersion
|
||||
AppUpgradeVersion _convertToAppUpgradeVersion(Map<String, dynamic> model) {
|
||||
// 将文件大小从 KB 转换为字节
|
||||
final int? apkSizeBytes = model['fileSize'] != null ? model['fileSize'] * 1024 : null;
|
||||
final filePath = model['filePath'];
|
||||
final appUpgradeVersion = AppUpgradeVersion(
|
||||
versionName: model['versionName'],
|
||||
versionBuildNumber: model['version'],
|
||||
isForce: model['isforce'],
|
||||
updateContent: model['remark'],
|
||||
downloadUrl: filePath,
|
||||
appStoreUrl: filePath,
|
||||
apkSize: apkSizeBytes,
|
||||
apkMd5: null, // UpdateappResult 中没有 MD5 字段
|
||||
// appMarkets: null, // UpdateappResult 中没有应用商店列表字段
|
||||
supportedMethods: [AppUpgradeMethod.browser, AppUpgradeMethod.inApp, AppUpgradeMethod.market],
|
||||
// appMarkets: [
|
||||
// AppMarket.huawei,
|
||||
// // AppMarket.xiaomi,
|
||||
// ],
|
||||
);
|
||||
return appUpgradeVersion;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -123,24 +151,30 @@ class _HomePageState extends State<HomePage> {
|
|||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Running on: $_platformVersion\n'),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
AppUpgradeSimple.instance.checkUpdate(
|
||||
context: context,
|
||||
onPressed: () async {
|
||||
// 1. 静默检查更新(不显示任何 UI)
|
||||
final upgradeInfo = await AppUpgradeSimple.instance.silentCheckUpdate(
|
||||
future: () async {
|
||||
// 模拟获取服务器版本信息
|
||||
return AppUpgradeVersion(
|
||||
versionName: '1.0.1',
|
||||
versionBuildNumber: 11,
|
||||
updateContent: '这是一个新版本',
|
||||
downloadUrl: 'https://example.com/app.apk',
|
||||
);
|
||||
final updateAppEvent = await _getUpdateAppEvent();
|
||||
print("获取最新版本: $updateAppEvent");
|
||||
if (updateAppEvent == null) return null;
|
||||
|
||||
return _convertToAppUpgradeVersion(updateAppEvent);
|
||||
},
|
||||
showNoUpdateToast: false, // 禁用"已是最新版本"的提示
|
||||
autoInstall: false,
|
||||
);
|
||||
// 2. 根据结果处理
|
||||
if (upgradeInfo != null && upgradeInfo.hasUpdate) {
|
||||
// 有新版本,可以显示红点或在用户点击时调用弹窗
|
||||
print('发现新版本: ${upgradeInfo.versionName}');
|
||||
|
||||
// 在需要展示弹窗的时机(如用户点击按钮):
|
||||
AppUpgradeSimple.instance.showPreparedUpgrade(
|
||||
context: context,
|
||||
info: upgradeInfo, // 传入刚才获取的 info
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('检查更新'),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,557 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
dio:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dio
|
||||
sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.9.0"
|
||||
dio_web_adapter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dio_web_adapter
|
||||
sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_driver:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
fuchsia_remote_debug_protocol:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.6.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
integration_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "11.0.2"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.10"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
package_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "9.0.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.22"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.5.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
permission_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "12.0.1"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "13.0.1"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "9.4.7"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.3+5"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.6"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.0.5"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
sync_http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sync_http
|
||||
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.7.6"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.3.28"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.3.6"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.2.5"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.5"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "15.0.2"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webdriver
|
||||
sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.15.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
yx_app_upgrade_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0"
|
||||
sdks:
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
flutter: ">=3.35.0"
|
||||
|
|
@ -32,7 +32,6 @@ dependencies:
|
|||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.8
|
||||
permission_handler: ^11.3.1
|
||||
|
||||
dev_dependencies:
|
||||
integration_test:
|
||||
|
|
|
|||
|
|
@ -5,104 +5,97 @@
|
|||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:yx_app_upgrade_flutter/app_upgrade_plugin.dart';
|
||||
import 'package:yx_app_upgrade_flutter/app_upgrade_plugin_enhanced.dart';
|
||||
import 'package:app_upgrade_plugin_example/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:yx_app_upgrade_flutter/app_upgrade_plugin.dart';
|
||||
import 'package:yx_app_upgrade_flutter/app_upgrade_plugin_platform_interface.dart';
|
||||
|
||||
class MockAppUpgradePluginEnhanced implements AppUpgradePluginEnhanced {
|
||||
// 在这里 mock AppUpgradePluginEnhanced 的所有方法和属性
|
||||
// ...
|
||||
// 你可以根据测试需要返回特定的值
|
||||
/// Mock implementation of AppUpgradePluginPlatform for testing
|
||||
class MockAppUpgradePluginPlatform extends AppUpgradePluginPlatform {
|
||||
MockAppUpgradePluginPlatform() : super();
|
||||
|
||||
@override
|
||||
void addDownloadCallback(DownloadCallback callback) {}
|
||||
Future<String?> getPlatformVersion() async => 'Mock Platform 1.0.0';
|
||||
|
||||
@override
|
||||
void addErrorCallback(ErrorCallback callback) {}
|
||||
Future<int?> getAndroidSdkVersion() async => 33;
|
||||
|
||||
@override
|
||||
void addUpgradeCallback(UpgradeCallback callback) {}
|
||||
Future<bool> openInstallPermissionSettings() async => true;
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>?> getDeviceInfo() async => {
|
||||
'manufacturer': 'Mock Manufacturer',
|
||||
'model': 'Mock Model',
|
||||
'androidVersion': '13',
|
||||
};
|
||||
|
||||
@override
|
||||
Future<List<String>> getInstalledMarkets() async => ['huawei', 'xiaomi'];
|
||||
|
||||
@override
|
||||
void configureHttp(HttpConfig config) {
|
||||
// Mock implementation
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, String>> getAppInfo() async => {
|
||||
'appName': 'app_upgrade_plugin_example',
|
||||
'packageName': 'com.example.app_upgrade_plugin_example',
|
||||
'version': '1.0.0',
|
||||
'buildNumber': '1',
|
||||
};
|
||||
|
||||
@override
|
||||
Future<UpgradeInfo?> checkUpdate(String url, {Map<String, dynamic>? params}) async {
|
||||
// Return null to simulate no update available
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> downloadApk(
|
||||
String url, {
|
||||
Function(DownloadProgress)? onProgress,
|
||||
String? savePath,
|
||||
}) async {
|
||||
// Simulate download progress
|
||||
if (onProgress != null) {
|
||||
onProgress(DownloadProgress(received: 50, total: 100));
|
||||
await Future.delayed(const Duration(milliseconds: 10));
|
||||
onProgress(DownloadProgress(received: 100, total: 100));
|
||||
}
|
||||
return '/mock/path/to/downloaded.apk';
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> installApk(String filePath) async => true;
|
||||
|
||||
@override
|
||||
Future<bool> installApkWithSystemFlow(String filePath) async => true;
|
||||
|
||||
@override
|
||||
Future<bool> installApkWithConfig(String filePath, InstallConfig config) async => true;
|
||||
|
||||
@override
|
||||
Future<bool> goToAppStore(String url, {required BuildContext context}) async => true;
|
||||
|
||||
@override
|
||||
Future<String?> getDownloadPath({bool checkPermission = true}) async => '/mock/download/path';
|
||||
|
||||
@override
|
||||
Future<bool> checkApkExists(String version, String? md5) async => false;
|
||||
@override
|
||||
Future<UpgradeInfo?> checkUpdateSmart(String url,
|
||||
{Map<String, dynamic>? params, bool forceRefresh = false, Duration? cacheDuration}) async =>
|
||||
null;
|
||||
@override
|
||||
Future<void> clearCache() async {}
|
||||
@override
|
||||
UpgradeConfig get config => UpgradeConfig.instance;
|
||||
@override
|
||||
void configure(
|
||||
{bool? debugMode,
|
||||
int? checkIntervalHours,
|
||||
bool? autoCheck,
|
||||
bool? wifiOnly,
|
||||
int? downloadTimeout,
|
||||
int? connectTimeout,
|
||||
int? maxRetryCount,
|
||||
bool? supportBreakpoint,
|
||||
bool? verifyIntegrity,
|
||||
VersionCompareStrategy? versionStrategy,
|
||||
Map<String, String>? customHeaders}) {}
|
||||
@override
|
||||
void dispose() {}
|
||||
@override
|
||||
Future<String?> downloadApkSmart(String url,
|
||||
{String? versionName,
|
||||
Function(DownloadProgress p1)? onProgress,
|
||||
String? savePath,
|
||||
String? md5,
|
||||
String? sha256,
|
||||
bool resumeIfExists = true}) async =>
|
||||
null;
|
||||
@override
|
||||
Future<Map<String, String>> getAppInfo() async => {};
|
||||
@override
|
||||
Future<Map<String, dynamic>> getCacheStats() async => {};
|
||||
@override
|
||||
DownloadTask? getCurrentDownloadTask() => null;
|
||||
@override
|
||||
Future<String?> getPlatformVersion() async => 'mock';
|
||||
@override
|
||||
Future<bool> goToAppStore(String url) async => false;
|
||||
@override
|
||||
Future<bool> installApkSmart(String filePath) async => false;
|
||||
@override
|
||||
NetworkStatus? get networkStatus => NetworkStatus(
|
||||
type: NetworkType.wifi,
|
||||
quality: NetworkQuality.good,
|
||||
isConnected: true,
|
||||
isMetered: false,
|
||||
);
|
||||
@override
|
||||
void pauseDownload() {}
|
||||
@override
|
||||
void removeDownloadCallback(DownloadCallback callback) {}
|
||||
@override
|
||||
void removeErrorCallback(ErrorCallback callback) {}
|
||||
@override
|
||||
void removeUpgradeCallback(UpgradeCallback callback) {}
|
||||
@override
|
||||
Future<bool> resumeDownload() async => false;
|
||||
@override
|
||||
Future<bool> retryDownload() async => false;
|
||||
@override
|
||||
Future<void> refreshNetworkStatus() async {}
|
||||
@override
|
||||
VersionComparator get versionComparator => VersionComparator();
|
||||
@override
|
||||
void cancelDownload() {}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// 关键修复:确保测试绑定已初始化
|
||||
// Ensure test bindings are initialized
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
setUp(() {
|
||||
// 为所有方法通道设置一个默认的 mock 处理器,防止未 mock 的调用抛出异常
|
||||
// Set up mock method channel handlers for platform channels
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('plugins.flutter.io/package_info'),
|
||||
const MethodChannel('plugins.flutter.io/package_info_plus'),
|
||||
(MethodCall methodCall) async {
|
||||
if (methodCall.method == 'getAll') {
|
||||
return <String, dynamic>{
|
||||
|
|
@ -116,45 +109,177 @@ void main() {
|
|||
},
|
||||
);
|
||||
|
||||
// Mock local notifications channel
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('dexterous.com/flutter/local_notifications'),
|
||||
(MethodCall methodCall) async => null, // 对通知插件的所有调用都返回 null
|
||||
(MethodCall methodCall) async => null,
|
||||
);
|
||||
|
||||
// Mock connectivity channel
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('dev.flutter.plugins/connectivity'),
|
||||
(MethodCall methodCall) async {
|
||||
if (methodCall.method == 'check') {
|
||||
return 'wifi'; // 模拟网络状态为 WiFi
|
||||
return 'wifi';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
|
||||
// Set mock platform implementation
|
||||
AppUpgradePluginPlatform.instance = MockAppUpgradePluginPlatform();
|
||||
});
|
||||
|
||||
testWidgets('Verify Platform version', (WidgetTester tester) async {
|
||||
// 使用 Mock enhanced plugin
|
||||
AppUpgradeSimple.instance = AppUpgradeSimple.private(plugin: MockAppUpgradePluginEnhanced());
|
||||
tearDown(() {
|
||||
// Clean up method channel handlers
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('plugins.flutter.io/package_info_plus'),
|
||||
null,
|
||||
);
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('dexterous.com/flutter/local_notifications'),
|
||||
null,
|
||||
);
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('dev.flutter.plugins/connectivity'),
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
group('App Upgrade Plugin Widget Tests', () {
|
||||
testWidgets('App should launch successfully', (WidgetTester tester) async {
|
||||
// Build the app
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// 只验证应用能正常启动,不验证具体的UI内容
|
||||
// Verify that the app widget is present
|
||||
expect(find.byType(MyApp), findsOneWidget);
|
||||
expect(find.byType(HomePage), findsOneWidget);
|
||||
|
||||
// Verify that the app bar is present
|
||||
expect(find.text('App Upgrade Plugin 示例'), findsOneWidget);
|
||||
|
||||
// Verify that the check update button is present
|
||||
expect(find.text('检查更新'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Verify Network Status Detection', (WidgetTester tester) async {
|
||||
// 使用 Mock enhanced plugin
|
||||
final mockPlugin = MockAppUpgradePluginEnhanced();
|
||||
AppUpgradeSimple.instance = AppUpgradeSimple.private(plugin: mockPlugin);
|
||||
|
||||
testWidgets('App should display home page correctly', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const MyApp());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 验证网络状态检测功能
|
||||
final networkStatus = mockPlugin.networkStatus;
|
||||
// Verify UI elements
|
||||
expect(find.byType(Scaffold), findsOneWidget);
|
||||
expect(find.byType(AppBar), findsOneWidget);
|
||||
expect(find.byType(ElevatedButton), findsOneWidget);
|
||||
});
|
||||
|
||||
expect(networkStatus, isNotNull);
|
||||
expect(networkStatus!.isConnected, isTrue);
|
||||
expect(networkStatus.type, equals(NetworkType.wifi));
|
||||
expect(networkStatus.isMetered, isFalse);
|
||||
testWidgets('Check update button should be tappable', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const MyApp());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Find and tap the check update button
|
||||
final button = find.text('检查更新');
|
||||
expect(button, findsOneWidget);
|
||||
|
||||
// Tap the button
|
||||
await tester.tap(button);
|
||||
await tester.pump();
|
||||
|
||||
// Button should still be present after tap
|
||||
expect(button, findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
group('App Upgrade Plugin Platform Tests', () {
|
||||
test('getPlatformVersion should return mock version', () async {
|
||||
final platform = AppUpgradePluginPlatform.instance;
|
||||
final version = await platform.getPlatformVersion();
|
||||
expect(version, isNotNull);
|
||||
expect(version, equals('Mock Platform 1.0.0'));
|
||||
});
|
||||
|
||||
test('getAppInfo should return mock app info', () async {
|
||||
final platform = AppUpgradePluginPlatform.instance;
|
||||
final appInfo = await platform.getAppInfo();
|
||||
expect(appInfo, isNotNull);
|
||||
expect(appInfo['appName'], equals('app_upgrade_plugin_example'));
|
||||
expect(appInfo['version'], equals('1.0.0'));
|
||||
});
|
||||
|
||||
test('checkUpdate should return null when no update available', () async {
|
||||
final platform = AppUpgradePluginPlatform.instance;
|
||||
final upgradeInfo = await platform.checkUpdate('https://example.com/check');
|
||||
expect(upgradeInfo, isNull);
|
||||
});
|
||||
|
||||
test('getDownloadPath should return mock path', () async {
|
||||
final platform = AppUpgradePluginPlatform.instance;
|
||||
final path = await platform.getDownloadPath();
|
||||
expect(path, isNotNull);
|
||||
expect(path, equals('/mock/download/path'));
|
||||
});
|
||||
|
||||
test('checkApkExists should return false for non-existent APK', () async {
|
||||
final platform = AppUpgradePluginPlatform.instance;
|
||||
final exists = await platform.checkApkExists('1.0.0', null);
|
||||
expect(exists, isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('AppUpgradeVersion Model Tests', () {
|
||||
test('AppUpgradeVersion should be created correctly', () {
|
||||
final version = AppUpgradeVersion(
|
||||
versionName: '1.0.1',
|
||||
versionBuildNumber: 2,
|
||||
updateContent: 'Test update content',
|
||||
downloadUrl: 'https://example.com/app.apk',
|
||||
isForce: false,
|
||||
);
|
||||
|
||||
expect(version.versionName, equals('1.0.1'));
|
||||
expect(version.versionBuildNumber, equals(2));
|
||||
expect(version.updateContent, equals('Test update content'));
|
||||
expect(version.downloadUrl, equals('https://example.com/app.apk'));
|
||||
expect(version.isForce, isFalse);
|
||||
});
|
||||
|
||||
test('AppUpgradeVersion with force update should work', () {
|
||||
final version = AppUpgradeVersion(
|
||||
versionName: '1.0.1',
|
||||
versionBuildNumber: 2,
|
||||
updateContent: 'Force update',
|
||||
isForce: true,
|
||||
);
|
||||
|
||||
expect(version.isForce, isTrue);
|
||||
});
|
||||
|
||||
test('AppUpgradeVersion.getAppStoreByUrl should generate correct URL', () {
|
||||
final url = AppUpgradeVersion.getAppStoreByUrl('123456');
|
||||
expect(url, equals('https://apps.apple.com/cn/app/123456'));
|
||||
});
|
||||
|
||||
test('AppUpgradeVersion.getAppStoreByItunes should generate correct URL', () {
|
||||
final url = AppUpgradeVersion.getAppStoreByItunes('123456');
|
||||
expect(url, equals('itms-apps://itunes.apple.com/app/id123456'));
|
||||
});
|
||||
});
|
||||
|
||||
group('DownloadProgress Model Tests', () {
|
||||
test('DownloadProgress should calculate progress correctly', () {
|
||||
final progress = DownloadProgress(received: 50, total: 100);
|
||||
expect(progress.progress, equals(0.5));
|
||||
expect(progress.percentage, equals(50));
|
||||
});
|
||||
|
||||
test('DownloadProgress with zero total should handle gracefully', () {
|
||||
final progress = DownloadProgress(received: 0, total: 0);
|
||||
expect(progress.progress, equals(0.0));
|
||||
expect(progress.percentage, equals(0));
|
||||
});
|
||||
|
||||
test('DownloadProgress should calculate percentage correctly', () {
|
||||
final progress = DownloadProgress(received: 75, total: 100);
|
||||
expect(progress.percentage, equals(75));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue