From 01894461564b25cd12fb0ccdc61ec819f990b623 Mon Sep 17 00:00:00 2001 From: Victor Eronmosele Date: Sat, 12 Oct 2024 02:02:24 +0100 Subject: [PATCH 1/3] test: add ui tests for `TransactionTile` widget --- .../transaction/transaction_tile_test.dart | 205 ++++++++++++++++++ test/helpers/mocks.dart | 8 +- test/helpers/test_data.dart | 14 ++ 3 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 test/features/transaction/transaction_tile_test.dart diff --git a/test/features/transaction/transaction_tile_test.dart b/test/features/transaction/transaction_tile_test.dart new file mode 100644 index 00000000..adffaea2 --- /dev/null +++ b/test/features/transaction/transaction_tile_test.dart @@ -0,0 +1,205 @@ +import 'package:didpay/features/transaction/transaction.dart'; +import 'package:didpay/features/transaction/transaction_details_page.dart'; +import 'package:didpay/features/transaction/transaction_notifier.dart'; +import 'package:didpay/features/transaction/transaction_tile.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../helpers/mocks.dart'; +import '../../helpers/test_data.dart'; +import '../../helpers/widget_helpers.dart'; + +void main() { + group('TransactionTile', () { + final pfi = TestData.getPfi('did:dht:pfiDid'); + const exchangeId = 'rfq_01ha835rhefwmagsknrrhvaa0k'; + + final sendTransaction = TestData.getTransaction(); + final depositTransaction = TestData.getTransaction( + type: TransactionType.deposit, + ); + final withdrawTransaction = TestData.getTransaction( + type: TransactionType.withdraw, + ); + + const mockTransactionNotifierWithSendTransaction = + MockTransactionNotifierWithData( + transactionType: TransactionType.send, + ); + const mockTransactionNotifierWithDepositTransaction = + MockTransactionNotifierWithData( + transactionType: TransactionType.deposit, + ); + const mockTransactionNotifierWithWithdrawTransaction = + MockTransactionNotifierWithData( + transactionType: TransactionType.withdraw, + ); + const mockTransactionNotifierWithNullData = + MockTransactionNotifierWithNullData(); + const mockTransactionNotifierWithError = MockTransactionNotifierWithError(); + + late MockTransactionNotifier mockSendTransactionNotifier; + late MockTransactionNotifier mockDepositTransactionNotifier; + late MockTransactionNotifier mockWithdrawTransactionNotifier; + late MockTransactionNotifier nullMockTransactionNotifier; + late MockTransactionNotifier erroringMockTransactionNotifier; + + setUp(() { + mockSendTransactionNotifier = + MockTransactionNotifier(() => sendTransaction); + mockDepositTransactionNotifier = + MockTransactionNotifier(() => depositTransaction); + mockWithdrawTransactionNotifier = + MockTransactionNotifier(() => withdrawTransaction); + nullMockTransactionNotifier = MockTransactionNotifier(); + erroringMockTransactionNotifier = MockTransactionNotifier( + () => throw StateError('Error loading transaction'), + ); + }); + + Widget transactionTileTestWidget({ + required MockTransactionNotifierType mockTransactionNotifierType, + }) => + WidgetHelpers.testableWidget( + child: TransactionTile( + pfi: pfi, + exchangeId: exchangeId, + ), + overrides: [ + transactionProvider.overrideWith( + () => switch (mockTransactionNotifierType) { + MockTransactionNotifierWithData() => switch ( + mockTransactionNotifierType.transactionType) { + TransactionType.send => mockSendTransactionNotifier, + TransactionType.deposit => mockDepositTransactionNotifier, + TransactionType.withdraw => mockWithdrawTransactionNotifier, + }, + MockTransactionNotifierWithNullData() => + nullMockTransactionNotifier, + MockTransactionNotifierWithError() => + erroringMockTransactionNotifier, + }, + ), + ], + ); + + testWidgets('should show paying and payout currencies', (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: + mockTransactionNotifierWithSendTransaction, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('AUD → BTC'), findsOneWidget); + }); + + testWidgets('should show transaction status', (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: + mockTransactionNotifierWithSendTransaction, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('Order submitted'), findsOneWidget); + }); + + testWidgets('should show error if transaction is null', (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: mockTransactionNotifierWithNullData, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('No transactions found'), findsOneWidget); + }); + + testWidgets('should show error when transaction fetch returns an error', + (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: mockTransactionNotifierWithError, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('Bad state: Error loading transaction'), findsOneWidget); + }); + + group('should show transaction amount in correct format for ', () { + testWidgets('send transactions', (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: + mockTransactionNotifierWithSendTransaction, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('-100.01 AUD'), findsOneWidget); + }); + + testWidgets('deposit transactions', (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: + mockTransactionNotifierWithDepositTransaction, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('+0.12 BTC'), findsOneWidget); + }); + + testWidgets('withdraw transactions', (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: + mockTransactionNotifierWithWithdrawTransaction, + ), + ); + await tester.pumpAndSettle(); + + expect(find.text('+100.01 AUD'), findsOneWidget); + }); + }); + + testWidgets('should navigate to transaction details page on tap', + (tester) async { + await tester.pumpWidget( + transactionTileTestWidget( + mockTransactionNotifierType: + mockTransactionNotifierWithSendTransaction, + ), + ); + + await tester.pumpAndSettle(); + await tester.tap(find.widgetWithText(ListTile, 'AUD → BTC')); + + await tester.pumpAndSettle(); + expect(find.byType(TransactionDetailsPage), findsOneWidget); + }); + }); +} + +sealed class MockTransactionNotifierType { + const MockTransactionNotifierType(); +} + +class MockTransactionNotifierWithData extends MockTransactionNotifierType { + const MockTransactionNotifierWithData({required this.transactionType}); + + final TransactionType transactionType; +} + +class MockTransactionNotifierWithNullData extends MockTransactionNotifierType { + const MockTransactionNotifierWithNullData(); +} + +class MockTransactionNotifierWithError extends MockTransactionNotifierType { + const MockTransactionNotifierWithError(); +} diff --git a/test/helpers/mocks.dart b/test/helpers/mocks.dart index aff98b3a..64687fcb 100644 --- a/test/helpers/mocks.dart +++ b/test/helpers/mocks.dart @@ -53,7 +53,13 @@ class MockFeatureFlagsNotifier extends StateNotifier> class MockTransactionNotifier extends AutoDisposeFamilyAsyncNotifier< Transaction?, TransactionProviderParameters> with Mock implements TransactionNotifier { - MockTransactionNotifier(); + final Transaction? Function()? transactionBuilder; + + MockTransactionNotifier([this.transactionBuilder]); + + @override + FutureOr build(TransactionProviderParameters arg) async => + transactionBuilder?.call(); } class MockTbdexQuoteNotifier extends AutoDisposeAsyncNotifier diff --git a/test/helpers/test_data.dart b/test/helpers/test_data.dart index 7edafd0e..f54e392f 100644 --- a/test/helpers/test_data.dart +++ b/test/helpers/test_data.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:didpay/features/account/account_balance.dart'; import 'package:didpay/features/feature_flags/feature_flag.dart'; import 'package:didpay/features/pfis/pfi.dart'; +import 'package:didpay/features/transaction/transaction.dart'; import 'package:json_schema/json_schema.dart'; import 'package:tbdex/tbdex.dart'; import 'package:typeid/typeid.dart'; @@ -151,4 +152,17 @@ class TestData { } '''), ); + + static Transaction getTransaction({ + TransactionType type = TransactionType.send, + }) => + Transaction( + payinAmount: '100.01', + payoutAmount: '0.12', + payinCurrency: 'AUD', + payoutCurrency: 'BTC', + createdAt: DateTime(2024), + type: type, + status: TransactionStatus.orderSubmitted, + ); } From 7aade31105e989c217781973a26655a71241290a Mon Sep 17 00:00:00 2001 From: Victor Eronmosele Date: Tue, 15 Oct 2024 19:28:28 +0100 Subject: [PATCH 2/3] chore: update transaction tile test description --- test/features/transaction/transaction_tile_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/features/transaction/transaction_tile_test.dart b/test/features/transaction/transaction_tile_test.dart index adffaea2..ece17be7 100644 --- a/test/features/transaction/transaction_tile_test.dart +++ b/test/features/transaction/transaction_tile_test.dart @@ -83,7 +83,7 @@ void main() { ], ); - testWidgets('should show paying and payout currencies', (tester) async { + testWidgets('should show payin and payout currencies', (tester) async { await tester.pumpWidget( transactionTileTestWidget( mockTransactionNotifierType: From ee2cf7ba01c4fb7d8c6d70e24f5df0c820c0de30 Mon Sep 17 00:00:00 2001 From: Victor Eronmosele Date: Tue, 15 Oct 2024 19:33:27 +0100 Subject: [PATCH 3/3] chore: remove extra variable in transaction tile test --- test/features/transaction/transaction_tile_test.dart | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/features/transaction/transaction_tile_test.dart b/test/features/transaction/transaction_tile_test.dart index ece17be7..5e5b041f 100644 --- a/test/features/transaction/transaction_tile_test.dart +++ b/test/features/transaction/transaction_tile_test.dart @@ -11,9 +11,6 @@ import '../../helpers/widget_helpers.dart'; void main() { group('TransactionTile', () { - final pfi = TestData.getPfi('did:dht:pfiDid'); - const exchangeId = 'rfq_01ha835rhefwmagsknrrhvaa0k'; - final sendTransaction = TestData.getTransaction(); final depositTransaction = TestData.getTransaction( type: TransactionType.deposit, @@ -62,8 +59,8 @@ void main() { }) => WidgetHelpers.testableWidget( child: TransactionTile( - pfi: pfi, - exchangeId: exchangeId, + pfi: TestData.getPfi('did:dht:pfiDid'), + exchangeId: 'rfq_01ha835rhefwmagsknrrhvaa0k', ), overrides: [ transactionProvider.overrideWith(