// 功能描述:账单金额严格解析、筛选请求和过期会话保护;版本:1.0.0。 import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:user_app/data/repositories/client_repository.dart'; import 'package:user_app/data/services/api_client.dart'; import 'package:user_app/domain/models/wallet_bill.dart'; void main() { test('钱包缺失或小数金额不能显示为零余额', () async { for (final data in [ '{}', '{"balance":1.5,"withdrawal_balance":0}', '{"balance":0,"withdrawal_balance":1}', ]) { final repo = ClientRepository( ApiClient( () => 't', client: MockClient((_) async => http.Response('{"code":0,"details":$data}', 200)), ), ); await expectLater(repo.wallet(), throwsA(isA())); } }); final valid = { 'identity': 'r1', 'direction': 'expense', 'amount': 100, 'fee': 0, 'balance_after': 500, 'created_at': '2026-09-08T08:00:00Z', }; test('金额和收支不推测、不截断为整数', () { expect(WalletBill.fromJson(valid).signedAmount, '-¥1.00'); for (final patch in [ {'amount': 1.5}, {'amount': -1}, {'fee': '0'}, {'direction': 'unknown'}, {'created_at': ''}, ]) { expect(() => WalletBill.fromJson({...valid, ...patch}), throwsFormatException); } }); test('账单筛选和游标传递,不将错误响应当空列表', () async { final repo = ClientRepository( ApiClient( () => 't', client: MockClient((r) async { expect(r.url.queryParameters, {'direction': 'income', 'cursor': '50'}); return http.Response('{"code":0,"details":{}}', 200); }), ), ); await expectLater( repo.walletBills(direction: 'income', cursor: '50'), throwsA(isA()), ); }); test('切换账户后迟到的账单不可显示', () async { var token = 'alice'; final repo = ClientRepository( ApiClient( () => token, client: MockClient((r) async { token = 'bob'; return http.Response('{"code":0,"details":{"items":[],"next_cursor":""}}', 200); }), ), ); await expectLater(repo.walletBills(), throwsA(isA())); }); }