import 'package:dio/dio.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:jinzhi_flutter_app/features/mall/application/mall_tab_config.dart'; import 'package:jinzhi_flutter_app/models/pb/jinzhi/v1/ads.pb.dart' as pb; void main() { test('keeps click attribution and reports the full generated event', () async { pb.ReportAdEventRequest? clickEvent; final dio = Dio() ..interceptors.add( InterceptorsWrapper( onRequest: (options, handler) { if (options.path == '/api/v1/ads') { handler.resolve( Response>( requestOptions: options, statusCode: 200, data: pb.GetAdReply( enabled: true, ad: pb.AdCreative( adId: 'ad-1', h5Url: 'https://mall.example.com', trackingId: 'tracking-1', openMode: pb.AdOpenMode.AD_OPEN_MODE_IN_APP, ), ).writeToBuffer(), ), ); return; } if (options.path == '/api/v1/ads/events') { final event = pb.ReportAdEventRequest.fromBuffer( options.data as List, ); if (event.eventName == 'ad_click') clickEvent = event; handler.resolve( Response>( requestOptions: options, statusCode: 200, data: pb.ReportAdEventReply().writeToBuffer(), ), ); return; } handler.next(options); }, ), ); final controller = MallTabConfigController(dio, autoRefresh: false); await controller.refresh(); final clicked = await controller.recordClick( request: MallEntryRequest.quoteRetailGold, ); expect(clicked.clickId, isNotEmpty); expect(controller.state.clickId, clicked.clickId); expect(clickEvent?.clickId, clicked.clickId); expect(clickEvent?.attrs['source_app'], 'jinzhi'); expect(clickEvent?.attrs['source_entry'], 'market_quote'); expect(clickEvent?.attrs['hook_type'], 'quote_cta'); expect(clickEvent?.attrs['entry_scene'], 'retail'); expect(clickEvent?.attrs['entry_metal'], 'au'); expect(clickEvent?.attrs['open_mode'], 'in_app'); }); }