feat(app): 接入金币充值与会员商品下单

This commit is contained in:
Zhou Weidong committed 2026-10-20 04:32:03 +08:00
1 parent ec2db6842e
commit 730e38622f
21 files changed
+1325 -1

No files matched your search

+108
View File
@@ -0,0 +1,108 @@
// Author: fruit.com.cn
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/core/data/models/order.dart';
import 'package:fruitshorts/core/data/models/product.dart';
import 'package:fruitshorts/core/data/remote/api_exception.dart';
import 'package:fruitshorts/core/data/repositories/store_repository.dart';
import 'package:fruitshorts/core/data/services/store_controller.dart';
void main() {
test('should_expose_coin_packs_when_store_loads', () async {
final repository = _FakeStoreRepository(
products: [_product('550 Coins', coinAmount: 500, bonusCoin: 50)],
);
final controller = StoreController(
repository,
type: StoreController.coinPackType,
);
await controller.load();
expect(repository.requestedTypes, [StoreController.coinPackType]);
expect(controller.products.single.name, '550 Coins');
expect(controller.error, isNull);
});
test('should_create_order_and_keep_purchase_when_buying', () async {
final repository = _FakeStoreRepository(
products: [_product('550 Coins')],
order: const AppOrder(
id: '99',
orderNo: 'ORD1',
productName: '550 Coins',
coinAmount: 550,
status: 'CREATED',
),
);
final controller = StoreController(
repository,
type: StoreController.coinPackType,
);
await controller.load();
final order = await controller.buy(controller.products.single);
expect(repository.orderedProductIds, ['2111012753262120962']);
expect(order?.orderNo, 'ORD1');
expect(controller.purchaseError, isNull);
expect(controller.purchasingProductId, isNull);
});
test('should_expose_server_message_when_order_is_rejected', () async {
final repository = _FakeStoreRepository(
products: [_product('550 Coins')],
orderError: const ApiException(400, 'Product is offline'),
);
final controller = StoreController(
repository,
type: StoreController.coinPackType,
);
await controller.load();
final order = await controller.buy(controller.products.single);
expect(order, isNull);
expect(controller.purchaseError, 'Product is offline');
});
}
AppProduct _product(String name, {int coinAmount = 550, int bonusCoin = 0}) =>
AppProduct(
id: '2111012753262120962',
code: 'coin_550',
name: name,
type: StoreController.coinPackType,
coinAmount: coinAmount,
bonusCoin: bonusCoin,
totalCoin: coinAmount + bonusCoin,
displayPrice: 'Rp 15.000',
vipDays: 0,
);
class _FakeStoreRepository implements StoreRepository {
_FakeStoreRepository({
this.products = const [],
this.order,
this.orderError,
});
final List<AppProduct> products;
final AppOrder? order;
final ApiException? orderError;
final List<String?> requestedTypes = [];
final List<String> orderedProductIds = [];
@override
Future<List<AppProduct>> fetchProducts({String? type}) async {
requestedTypes.add(type);
return products;
}
@override
Future<AppOrder> createOrder(String productId) async {
orderedProductIds.add(productId);
if (orderError != null) throw orderError!;
return order!;
}
}