Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
test: add ui tests for TransactionTile widget (#314)
Browse files Browse the repository at this point in the history
  • Loading branch information
victoreronmosele authored Oct 15, 2024
1 parent 5ebbfd3 commit 0bc1feb
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 1 deletion.
202 changes: 202 additions & 0 deletions test/features/transaction/transaction_tile_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
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 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: TestData.getPfi('did:dht:pfiDid'),
exchangeId: 'rfq_01ha835rhefwmagsknrrhvaa0k',
),
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 payin 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();
}
8 changes: 7 additions & 1 deletion test/helpers/mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ class MockFeatureFlagsNotifier extends StateNotifier<List<FeatureFlag>>
class MockTransactionNotifier extends AutoDisposeFamilyAsyncNotifier<
Transaction?,
TransactionProviderParameters> with Mock implements TransactionNotifier {
MockTransactionNotifier();
final Transaction? Function()? transactionBuilder;

MockTransactionNotifier([this.transactionBuilder]);

@override
FutureOr<Transaction?> build(TransactionProviderParameters arg) async =>
transactionBuilder?.call();
}

class MockTbdexQuoteNotifier extends AutoDisposeAsyncNotifier<Quote?>
Expand Down
14 changes: 14 additions & 0 deletions test/helpers/test_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -160,4 +161,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,
);
}

0 comments on commit 0bc1feb

Please sign in to comment.