todo_app/test/unit/todo_providers_test.dart
PeterChrz 514adde721
Some checks failed
CI / Static Analysis (push) Failing after 2m7s
CI / Tests (push) Has been skipped
Initial commit: Flutter todo app with Riverpod
2026-08-04 23:40:54 -04:00

118 lines
3.9 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:todo_app/features/todo/domain/entities/todo.dart';
import 'package:todo_app/features/todo/domain/entities/create_todo_params.dart';
import 'package:todo_app/features/todo/domain/repositories/todo_repository.dart';
import 'package:todo_app/features/todo/presentation/providers/todo_providers.dart';
class MockTodoRepository extends Mock implements TodoRepository {}
class FakeCreateTodoParams extends Fake implements CreateTodoParams {}
void main() {
late MockTodoRepository repository;
late ProviderContainer container;
final testTodo = Todo(
id: '1',
title: 'Test Todo',
priority: 'medium',
sortOrder: 0,
createdAt: DateTime(2026, 1, 1),
updatedAt: DateTime(2026, 1, 1),
);
setUpAll(() {
registerFallbackValue(FakeCreateTodoParams());
});
setUp(() {
repository = MockTodoRepository();
container = ProviderContainer(overrides: [
todoRepositoryProvider.overrideWithValue(repository),
]);
addTearDown(container.dispose);
});
group('todoListProvider', () {
test('builds with todo list from repository', () async {
when(() => repository.getTodos(
priorityFilter: any(named: 'priorityFilter'),
completedFilter: any(named: 'completedFilter'),
)).thenAnswer((_) async => [testTodo]);
await container.read(todoListProvider.future);
expect(container.read(todoListProvider).value, equals([testTodo]));
});
test('handles error state', () async {
when(() => repository.getTodos(
priorityFilter: any(named: 'priorityFilter'),
completedFilter: any(named: 'completedFilter'),
)).thenThrow(Exception('Failed'));
try {
await container.read(todoListProvider.future);
fail('Should have thrown');
} catch (_) {
expect(container.read(todoListProvider).hasError, isTrue);
}
});
});
group('todoDetailProvider', () {
test('returns todo by id', () async {
when(() => repository.getTodo('1')).thenAnswer((_) async => testTodo);
final result = await container.read(todoDetailProvider('1').future);
expect(result, equals(testTodo));
});
});
group('TodoListNotifier.createTodo', () {
test('creates todo and refreshes list', () async {
when(() => repository.getTodos(
priorityFilter: any(named: 'priorityFilter'),
completedFilter: any(named: 'completedFilter'),
)).thenAnswer((_) async => [testTodo]);
when(() => repository.createTodo(any())).thenAnswer((_) async => testTodo);
await container.read(todoListProvider.notifier).createTodo(
const CreateTodoParams(title: 'New'),
);
verify(() => repository.createTodo(any())).called(1);
});
});
group('TodoListNotifier.toggleTodo', () {
test('toggles and refreshes', () async {
when(() => repository.getTodos(
priorityFilter: any(named: 'priorityFilter'),
completedFilter: any(named: 'completedFilter'),
)).thenAnswer((_) async => [testTodo]);
when(() => repository.toggleTodo('1')).thenAnswer((_) async => testTodo);
await container.read(todoListProvider.notifier).toggleTodo('1');
verify(() => repository.toggleTodo('1')).called(1);
});
});
group('TodoListNotifier.deleteTodo', () {
test('deletes and refreshes', () async {
when(() => repository.getTodos(
priorityFilter: any(named: 'priorityFilter'),
completedFilter: any(named: 'completedFilter'),
)).thenAnswer((_) async => []);
when(() => repository.deleteTodo('1')).thenAnswer((_) async {});
await container.read(todoListProvider.notifier).deleteTodo('1');
verify(() => repository.deleteTodo('1')).called(1);
});
});
}