Skip to content

Commit

Permalink
[Mobile] [Test] 支出詳細UIテスト追加 #337
Browse files Browse the repository at this point in the history
  • Loading branch information
wakamenod committed Jul 22, 2023
1 parent 3cacbec commit a0943ef
Show file tree
Hide file tree
Showing 18 changed files with 134 additions and 29 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class TransactionsList extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final transactionsValue = ref.watch(fetchTransactionsProvider);

// TODO エラー表示のgoldens test追加
return AsyncValueWidget<List<Transaction>>(
value: transactionsValue,
data: (transactions) => transactions.isEmpty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ class Expense with _$Expense {

bool get isNew => id == '';

static Expense init() => Expense(
static Expense init(DateTime now) => Expense(
id: '',
title: const Title.pure(),
amount: const Amount.pure(),
date: DateTime.now().toRfc3339(),
date: now.toRfc3339(),
categoryID: '',
category: '',
locationID: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:suito/src/features/transactions/repositories/expense/expense_det
import 'package:suito/src/features/transactions/repositories/expense/expense_locations_repository.dart';
import 'package:suito/src/formz/amount.dart';
import 'package:suito/src/formz/title.dart' as formz_title;
import 'package:suito/src/utils/datetime_utils.dart';

import 'expense.dart';

Expand All @@ -14,7 +15,8 @@ part 'expense_form_controller.g.dart';
@riverpod
Future<Expense> expenseFuture(ExpenseFutureRef ref, {String? id}) async {
if (id == null) {
return Expense.init();
final now = ref.watch(currentTimeProvider);
return Expense.init(now);
}
final categoriesMap =
await ref.read(expenseCategoriesMapFutureProvider.future);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ class TransactionYearMonths extends _$TransactionYearMonths {
final repository = ref.read(transactionMonthsRepositoryProvider);
final res = await repository.fetchTransactionMonthsList();
// 現在月は常に入れるようにする
final current = currentYYYYMM();
final current = ref.watch(currentTimeProvider).toYYYYMM();
res.contains(current) ? null : res.add(current);
return res;
}
}

// トランザクション一覧の年月ドロップダウンで選択中の年月を管理する
final selectedYearMonthProvider = StateProvider<String>(
(ref) => currentYYYYMM(),
);
final selectedYearMonthProvider =
StateProvider<String>((ref) => ref.watch(currentTimeProvider).toYYYYMM());

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions mobile/lib/src/utils/datetime_utils.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';

final _yyyymmFormatter = DateFormat('yyyy-MM');
final _yyyymmddFormatter = DateFormat('yyyy-MM-dd');

String currentYYYYMM() {
return _yyyymmFormatter.format(DateTime.now());
}

extension DateExtension on DateTime {
String toYMD() {
return _yyyymmddFormatter.format(this);
}
}

extension DateTimeRFC3339 on DateTime {
String toYYYYMM() {
return _yyyymmFormatter.format(this);
}

String toRfc3339() {
return "${toString().split('.')[0].replaceAll(' ', 'T')}Z";
}
}

final currentTimeProvider = Provider<DateTime>((ref) {
return DateTime.now();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:mocktail/mocktail.dart';
import 'package:openapi/openapi.dart';

import '../../../../../mocks.dart';
import '../../../transactions_robot.dart';

void main() {
// TODO エラー時の表示テスト追加

group('ExpenseDetailView Golden test group', () {
testGoldens('Open ExpenseDetailView as registration for new expense',
(tester) async {
await loadAppFonts();
final r = TransactionsRobot(tester);
final now = DateTime(2023, 5, 1);
await r.pumpExpenseDetailScreen(id: null, now: now);
await screenMatchesGolden(tester, 'new_expense_detail');
});
});

testGoldens('Open ExpenseDetailView for updating a registered expense',
(tester) async {
await loadAppFonts();
final r = TransactionsRobot(tester);
final now = DateTime(2023, 5, 1);
final repository = MockExpenseDetailRepository();
final categoryRepo = MockExpenseCategoriesRepository();
final locationRepo = MockExpenseLocationsRepository();
const id = 'expense_id';
final category = ModelExpenseCategory((e) => e
..id = 'expense_category_id'
..name = 'Test Category');
final location = ModelExpenseLocation((e) => e
..id = 'expense_location_id'
..name = 'Test Location');
final res = ExpenseDetailRes((r) => r.expense.replace(ModelExpense((b) => b
..id = id
..title = 'registered title'
..localDate = '2023-05-03'
..memo = 'Some memo'
..amount = 400
..expenseCategoryID = category.id
..expenseLocationID = location.id)));
when(() => repository.fetchExpenseDetail(id))
.thenAnswer((_) => Future.value(res));
when(() => categoryRepo.fetchExpenseCategoriesList())
.thenAnswer((invocation) => Future.value([category]));
when(() => locationRepo.fetchExpenseLocationsList())
.thenAnswer((invocation) => Future.value([location]));
await r.pumpExpenseDetailScreen(
expenseRepo: repository,
categoryRepo: categoryRepo,
locationRepo: locationRepo,
id: id,
now: now);
await screenMatchesGolden(tester, 'update_expense_detail');
});
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import '../../transactions_robot.dart';

void main() {
group('Golden test group', () {
testGoldens('Empty list',
// skip because the default month selected in the dropdown differs depending on the test execution time
skip: true, (tester) async {
testGoldens('Empty list', (tester) async {
await loadAppFonts();
final r = TransactionsRobot(tester);
final repository = MockTransactionsRepository();
Expand All @@ -20,8 +18,9 @@ void main() {
.thenAnswer((_) => Future.value([]));
when(() => monthsRepository.fetchTransactionMonthsList())
.thenAnswer((_) => Future.value([]));
final now = DateTime(2023, 7, 1);
await r.pumpTransactionsScreen(
transactionsRepo: repository, monthsRepo: monthsRepository);
now: now, transactionsRepo: repository, monthsRepo: monthsRepository);
await screenMatchesGolden(tester, 'empty_list');
});

Expand Down Expand Up @@ -60,8 +59,9 @@ void main() {
..type = TransactionType.expense.value
..amount = 1300)
]));
final now = DateTime(2023, 7, 1);
await r.pumpTransactionsScreen(
transactionsRepo: repository, monthsRepo: monthsRepository);
now: now, transactionsRepo: repository, monthsRepo: monthsRepository);
await tester.pumpAndSettle();

await r.tapToggleButton();
Expand All @@ -80,8 +80,9 @@ void main() {
.thenAnswer((_) => Future.value([]));
when(() => monthsRepository.fetchTransactionMonthsList())
.thenAnswer((_) => Future.value([]));
final now = DateTime(2023, 7, 1);
await r.pumpTransactionsScreen(
transactionsRepo: repository, monthsRepo: monthsRepository);
now: now, transactionsRepo: repository, monthsRepo: monthsRepository);
await tester.pumpAndSettle();
r.expectEmptyLabelFound();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void main() {
group('expenseFormController', () {
test('register new expense - validation valid', () async {
final container = makeProviderContainer();
final exp = Expense.init();
final exp = Expense.init(DateTime.now());
final controller =
container.read(expenseFormControllerProvider(exp).notifier);
const title = 'New title value';
Expand Down Expand Up @@ -70,7 +70,7 @@ void main() {

test('register new expense - validation invalid', () async {
final container = makeProviderContainer();
final exp = Expense.init();
final exp = Expense.init(DateTime.now());
final controller =
container.read(expenseFormControllerProvider(exp).notifier);
const memo = 'Memo';
Expand Down
41 changes: 40 additions & 1 deletion mobile/test/src/features/transactions/transactions_robot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,28 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:suito/src/app_theme.dart';
import 'package:suito/src/features/transactions/presentations/transaction/transactions_list_empty_label.dart';
import 'package:suito/src/features/transactions/presentations/transaction_detail_screen.dart';
import 'package:suito/src/features/transactions/presentations/transactions_screen.dart';
import 'package:suito/src/features/transactions/repositories/expense/expense_categories_repository.dart';
import 'package:suito/src/features/transactions/repositories/expense/expense_detail_repository.dart';
import 'package:suito/src/features/transactions/repositories/expense/expense_locations_repository.dart';
import 'package:suito/src/features/transactions/repositories/transaction/transaction_months_repository.dart';
import 'package:suito/src/features/transactions/repositories/transaction/transactions_repository.dart';
import 'package:suito/src/features/transactions/services/transaction/transaction_service.dart';
import 'package:suito/src/utils/datetime_utils.dart';

class TransactionsRobot {
TransactionsRobot(this.tester);
final WidgetTester tester;

Future<void> pumpTransactionsScreen(
{TransactionsRepository? transactionsRepo,
TransactionMonthsRepository? monthsRepo}) async {
TransactionMonthsRepository? monthsRepo,
required DateTime now}) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
currentTimeProvider.overrideWithValue(now),
if (transactionsRepo != null)
transactionsRepositoryProvider.overrideWithValue(transactionsRepo),
if (monthsRepo != null)
Expand All @@ -29,6 +37,37 @@ class TransactionsRobot {
);
}

Future<void> pumpExpenseDetailScreen(
{ExpenseDetailRepository? expenseRepo,
ExpenseCategoriesRepository? categoryRepo,
ExpenseLocationsRepository? locationRepo,
required String? id,
required DateTime now}) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
currentTimeProvider.overrideWithValue(now),
if (expenseRepo != null)
expenseDetailRepositoryProvider.overrideWithValue(expenseRepo),
if (categoryRepo != null)
expenseCategoriesRepositoryProvider.overrideWithValue(
categoryRepo,
),
if (locationRepo != null)
expenseLocationsRepositoryProvider.overrideWithValue(
locationRepo,
)
],
child: MaterialApp(
home: TransactionDetailScreen(
id: id,
type: TransactionType.expense.value,
),
theme: AppTheme().create()),
),
);
}

void expectEmptyLabelFound() {
expect(find.byType(TransactionsListEmptyLabel), findsOneWidget);
}
Expand Down

0 comments on commit a0943ef

Please sign in to comment.