feat(client): 购买模型/仓库切 pay v2 契约(render_type 多态 + 分金额 + 订单列表)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jiu_client/models/license.dart';
|
||||
|
||||
void main() {
|
||||
group('PurchaseOrder.fromJson() — pay v2 契约', () {
|
||||
test('解析 redirect 形态(render_type/payload/amount_minor)', () {
|
||||
final order = PurchaseOrder.fromJson({
|
||||
'order_no': 'pay-abc123',
|
||||
'out_trade_no': 'pay-abc123',
|
||||
'render_type': 'redirect',
|
||||
'payload': {'url': 'https://pay.example.com/checkout/abc123'},
|
||||
'amount_minor': 299900,
|
||||
'currency': 'CNY',
|
||||
'subject': '酒库管理系统 - 年度授权',
|
||||
'pay_url': 'https://pay.example.com/checkout/abc123',
|
||||
'amount': '2999.00',
|
||||
});
|
||||
|
||||
expect(order.outTradeNo, 'pay-abc123');
|
||||
expect(order.renderType, 'redirect');
|
||||
expect(order.amountMinor, 299900);
|
||||
expect(order.currency, 'CNY');
|
||||
expect(order.subject, '酒库管理系统 - 年度授权');
|
||||
expect(order.redirectUrl, 'https://pay.example.com/checkout/abc123');
|
||||
// 兼容 getter:Task 7 前 purchase_card.dart 仍读 payUrl/amount
|
||||
expect(order.payUrl, order.redirectUrl);
|
||||
expect(order.amount, '2,999.00');
|
||||
});
|
||||
|
||||
test('解析 qr 形态 payload', () {
|
||||
final order = PurchaseOrder.fromJson({
|
||||
'out_trade_no': 'pay-qr1',
|
||||
'render_type': 'qr',
|
||||
'payload': {'qr_content': 'weixin://wxpay/bizpayurl?pr=xxx'},
|
||||
'amount_minor': 100,
|
||||
'currency': 'CNY',
|
||||
'subject': '月度授权',
|
||||
});
|
||||
|
||||
expect(order.renderType, 'qr');
|
||||
expect(order.qrContent, 'weixin://wxpay/bizpayurl?pr=xxx');
|
||||
expect(order.redirectUrl, '');
|
||||
});
|
||||
});
|
||||
|
||||
group('PurchaseStatusInfo.fromJson()', () {
|
||||
test('解析 paid 状态,amount_minor 优先于 amount 串', () {
|
||||
final status = PurchaseStatusInfo.fromJson({
|
||||
'out_trade_no': 'pay-abc123',
|
||||
'status': 'paid',
|
||||
'product_biz_code': 'annual',
|
||||
'amount_minor': 299900,
|
||||
'currency': 'CNY',
|
||||
'amount': '2999.00',
|
||||
'paid_at': '2026-07-10T10:00:00Z',
|
||||
'expires_at': '2027-07-10T00:00:00Z',
|
||||
});
|
||||
|
||||
expect(status.isPaid, isTrue);
|
||||
expect(status.amountMinor, 299900);
|
||||
expect(status.currency, 'CNY');
|
||||
expect(status.displayAmount, '2,999.00');
|
||||
expect(status.paidAt, isNotNull);
|
||||
expect(status.expiresAt, isNotNull);
|
||||
});
|
||||
|
||||
test('amount_minor 缺失时回退旧 amount 串', () {
|
||||
final status = PurchaseStatusInfo.fromJson({
|
||||
'out_trade_no': 'pay-legacy',
|
||||
'status': 'pending',
|
||||
'amount': '99.00',
|
||||
});
|
||||
|
||||
expect(status.amountMinor, 0);
|
||||
expect(status.displayAmount, '99.00');
|
||||
});
|
||||
});
|
||||
|
||||
group('PurchaseRecord.fromJson()(订单列表项)', () {
|
||||
test('解析完整订单列表项', () {
|
||||
final record = PurchaseRecord.fromJson({
|
||||
'out_trade_no': 'pay-abc123',
|
||||
'product_biz_code': 'annual',
|
||||
'amount_minor': 299900,
|
||||
'currency': 'CNY',
|
||||
'amount': '2999.00',
|
||||
'status': 'paid',
|
||||
'pay_url': 'https://pay.example.com/checkout/abc123',
|
||||
'user_name': '张三',
|
||||
'created_at': '2026-07-01T10:00:00Z',
|
||||
'paid_at': '2026-07-01T10:05:00Z',
|
||||
'renewed_to': '2027-07-01T00:00:00Z',
|
||||
});
|
||||
|
||||
expect(record.outTradeNo, 'pay-abc123');
|
||||
expect(record.productBizCode, 'annual');
|
||||
expect(record.amountMinor, 299900);
|
||||
expect(record.displayAmount, '2,999.00');
|
||||
expect(record.isPaid, isTrue);
|
||||
expect(record.userName, '张三');
|
||||
expect(record.createdAt, isNotNull);
|
||||
expect(record.paidAt, isNotNull);
|
||||
expect(record.renewedTo, isNotNull);
|
||||
});
|
||||
|
||||
test('缺省可选字段不报错', () {
|
||||
final record = PurchaseRecord.fromJson({
|
||||
'out_trade_no': 'pay-pending1',
|
||||
'product_biz_code': 'monthly',
|
||||
'amount_minor': 9900,
|
||||
'currency': 'CNY',
|
||||
'amount': '99.00',
|
||||
'status': 'pending',
|
||||
'pay_url': '',
|
||||
'user_name': '',
|
||||
});
|
||||
|
||||
expect(record.isPaid, isFalse);
|
||||
expect(record.paidAt, isNull);
|
||||
expect(record.renewedTo, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('PurchaseListResult.fromJson()', () {
|
||||
test('解析 items + total + summary', () {
|
||||
final result = PurchaseListResult.fromJson({
|
||||
'items': [
|
||||
{
|
||||
'out_trade_no': 'pay-1',
|
||||
'product_biz_code': 'annual',
|
||||
'amount_minor': 299900,
|
||||
'currency': 'CNY',
|
||||
'amount': '2999.00',
|
||||
'status': 'paid',
|
||||
'pay_url': '',
|
||||
'user_name': '张三',
|
||||
},
|
||||
],
|
||||
'total': 1,
|
||||
'summary': {
|
||||
'paid_total_minor': 299900,
|
||||
'paid_count': 1,
|
||||
'pending_count': 0,
|
||||
'total_count': 1,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.items.length, 1);
|
||||
expect(result.total, 1);
|
||||
expect(result.summary.paidTotalMinor, 299900);
|
||||
expect(result.summary.paidCount, 1);
|
||||
expect(result.summary.pendingCount, 0);
|
||||
expect(result.summary.totalCount, 1);
|
||||
});
|
||||
|
||||
test('空列表不报错', () {
|
||||
final result = PurchaseListResult.fromJson({'items': [], 'total': 0});
|
||||
expect(result.items, isEmpty);
|
||||
expect(result.summary.totalCount, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user