test(client): L1 数值格式化纯函数单测 + 从 widget 抽出(支柱3)

- lib/util/format.dart:抽出 formatSpeed/formatDuration(原私有于 connect_page
  _speed / connect_button _fmt,混在 widget 里没法单测)
- connect_page/connect_button 改用公共纯函数(渲染输出不变)
- test/unit/format_test.dart:10 用例覆盖速率 B/s→GB/s 各单位边界 +
  时长 HH:MM:SS 补零/小时不封顶/取模 60
- 验证:format 10 + widget 8 全过、analyze 无 error/warning

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-25 12:06:34 +08:00
parent 64f96fe018
commit cb6fc25bc9
4 changed files with 84 additions and 19 deletions
+2 -6
View File
@@ -12,6 +12,7 @@ import 'package:flutter/material.dart';
import '../pangolin_theme.dart';
import '../state/connection_provider.dart';
import '../util/format.dart';
import 'pangolin_icons.dart';
class ConnectButton extends StatefulWidget {
@@ -50,11 +51,6 @@ class _ConnectButtonState extends State<ConnectButton> with SingleTickerProvider
super.dispose();
}
String _fmt(Duration d) {
String two(int n) => n.toString().padLeft(2, '0');
return '${two(d.inHours)}:${two(d.inMinutes % 60)}:${two(d.inSeconds % 60)}';
}
@override
Widget build(BuildContext context) {
final c = context.pangolin;
@@ -124,7 +120,7 @@ class _ConnectButtonState extends State<ConnectButton> with SingleTickerProvider
Icon(icon, size: 50, color: fg),
const SizedBox(height: 6),
if (s == VpnPhase.on) ...[
Text(_fmt(widget.elapsed),
Text(formatDuration(widget.elapsed),
style: PangolinText.mono
.copyWith(color: fg, fontSize: 18, fontWeight: FontWeight.w600)),
Text(widget.secureLabel,