import 'dart:convert'; import 'dart:typed_data'; import 'package:dio/dio.dart'; import 'package:patbond_flutter/features/auth/auth_models.dart'; import 'package:patbond_flutter/features/auth/auth_repository.dart'; import 'package:patbond_flutter/features/auth/session_manager.dart'; /// 测试用内存 token 存储。 class InMemoryTokenStore implements TokenStore { final Map values = {}; @override Future read(String key) async => values[key]; @override Future write(String key, String value) async => values[key] = value; @override Future delete(String key) async => values.remove(key); } /// 测试用假认证仓库:各方法可注入行为,默认成功空实现。 class FakeAuthRepository implements AuthRepository { FakeAuthRepository({ this.loginHandler, this.registerHandler, this.restoreHandler, }); final Future Function()? loginHandler; final Future Function()? registerHandler; final Future Function()? restoreHandler; int loginCalls = 0; int registerCalls = 0; int logoutCalls = 0; @override Future login({required String username, required String password}) { loginCalls += 1; return loginHandler?.call() ?? Future.value(); } @override Future register({ required String username, required String phone, required String password, }) { registerCalls += 1; return registerHandler?.call() ?? Future.value(); } @override Future logout() async { logoutCalls += 1; } @override Future restoreSession() { return restoreHandler?.call() ?? Future.value(SessionRestoreResult.noSession); } @override Future me() async => throw UnimplementedError(); } /// mock dio:用假 HttpClientAdapter 返回预设响应并记录请求。 class FakeHttpAdapter implements HttpClientAdapter { FakeHttpAdapter(this.handler); final Future Function(RequestOptions options) handler; final List requests = []; @override Future fetch( RequestOptions options, Stream? requestStream, Future? cancelFuture, ) { requests.add(options); return handler(options); } @override void close({bool force = false}) {} } ResponseBody jsonResponse(int statusCode, Map body) { return ResponseBody.fromString( jsonEncode(body), statusCode, headers: { Headers.contentTypeHeader: [Headers.jsonContentType], }, ); } Map okEnvelope(Map data) => { 'code': 0, 'message': 'ok', 'data': data, }; Map errorEnvelope(int code, [String message = 'error']) => { 'code': code, 'message': message, 'data': null, }; Map tokenDataJson({ String access = 'access-1', String refresh = 'refresh-1', }) => { 'userId': 'user-1', 'tokenType': 'Bearer', 'accessToken': access, 'accessTokenExpiresAt': '2026-09-04T13:00:00+08:00', 'refreshToken': refresh, 'refreshTokenExpiresAt': '2026-10-04T12:00:00+08:00', }; AuthTokens sampleTokens({ String access = 'access-0', String refresh = 'refresh-0', }) => AuthTokens.fromJson(tokenDataJson(access: access, refresh: refresh));