已完成用户APP首期功能开发
交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
This commit is contained in:
126
apps/user_app/test/data/favorite_test.dart
Normal file
126
apps/user_app/test/data/favorite_test.dart
Normal file
@@ -0,0 +1,126 @@
|
||||
// 功能描述:收藏版本契约、跨入口同步及账号切换迟到响应保护;版本:1.0.0。
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
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/product_favorite.dart';
|
||||
import 'package:user_app/ui/features/shop/favorite_button.dart';
|
||||
|
||||
http.Response _response(Object details) => http.Response(
|
||||
jsonEncode({'code': 0, 'details': details}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
|
||||
void main() {
|
||||
testWidgets('两个入口同步服务端收藏状态,失败读取后不反转图标', (tester) async {
|
||||
var active = false, version = 0, fail = false;
|
||||
final repo = ClientRepository(
|
||||
ApiClient(
|
||||
() => 'test',
|
||||
client: MockClient((request) async {
|
||||
if (request.method == 'PUT') {
|
||||
final body = jsonDecode(request.body) as Map;
|
||||
expect(body['revision'], version == 0 ? '' : 'f:$version');
|
||||
if (fail) return http.Response('{"code":500}', 200);
|
||||
active = body['favorite'] as bool;
|
||||
version++;
|
||||
}
|
||||
return _response({
|
||||
'product_identity': 'p1',
|
||||
'favorite': active,
|
||||
'revision': version == 0 ? '' : 'f:$version',
|
||||
});
|
||||
}),
|
||||
),
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Row(
|
||||
children: [
|
||||
for (var i = 0; i < 2; i++)
|
||||
FavoriteButton(repository: repo, identity: 'p1', redirect: '/shop', name: '商品'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byTooltip('收藏 商品'), findsNWidgets(2));
|
||||
await tester.tap(find.byTooltip('收藏 商品').first);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byTooltip('取消收藏 商品'), findsNWidgets(2));
|
||||
fail = true;
|
||||
await tester.tap(find.byTooltip('取消收藏 商品').first);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byTooltip('取消收藏 商品'), findsNWidgets(2));
|
||||
});
|
||||
test('账号切换后不广播前一账号收藏结果', () async {
|
||||
var token = 'account-a';
|
||||
final pending = Completer<http.Response>();
|
||||
final events = <ProductFavoriteState>[];
|
||||
final repo = ClientRepository(
|
||||
ApiClient(() => token, client: MockClient((_) => pending.future)),
|
||||
);
|
||||
final subscription = repo.favoriteChanges.listen(events.add);
|
||||
addTearDown(subscription.cancel);
|
||||
final result = repo.setFavorite(
|
||||
const ProductFavoriteState(productIdentity: 'p1', active: false, revision: ''),
|
||||
true,
|
||||
);
|
||||
final assertion = expectLater(result, throwsA(isA<SessionExpiredException>()));
|
||||
token = 'account-b';
|
||||
pending.complete(_response({'product_identity': 'p1', 'favorite': true, 'revision': 'f:1'}));
|
||||
await assertion;
|
||||
expect(events, isEmpty);
|
||||
});
|
||||
test('收藏分页、图片URL及金额数据校验', () async {
|
||||
var reads = 0;
|
||||
final repo = ClientRepository(
|
||||
ApiClient(
|
||||
() => 'test',
|
||||
client: MockClient((request) async {
|
||||
reads++;
|
||||
final page = int.parse(request.url.queryParameters['page']!);
|
||||
return _response({
|
||||
'items': [
|
||||
{
|
||||
'product_identity': 'p$page',
|
||||
'favorite': true,
|
||||
'revision': 'r$page',
|
||||
'name': '商品$page',
|
||||
'price_amount': 16900,
|
||||
'stock_quantity': 0,
|
||||
'available': false,
|
||||
'category_name': '配件',
|
||||
'image_url': 'javascript:bad',
|
||||
'specifications': ['家用'],
|
||||
},
|
||||
],
|
||||
'has_more': page == 1,
|
||||
'page': page,
|
||||
'page_size': 30,
|
||||
});
|
||||
}),
|
||||
),
|
||||
);
|
||||
final items = await repo.favorites();
|
||||
expect(reads, 2);
|
||||
expect(items.length, 2);
|
||||
expect(items.first.product.imageUrl, '');
|
||||
expect(items.first.available, isFalse);
|
||||
expect(
|
||||
() => ProductFavoriteState.fromJson({
|
||||
'product_identity': 'p1',
|
||||
'favorite': 'true',
|
||||
'revision': '',
|
||||
}),
|
||||
throwsFormatException,
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user