- Created 8 separate BLoCs (Home, Library, BookDetails, AddBook, Scanner, Categories, Wishlist, Settings) - Each BLoC has its own event, state, and bloc files - Added 70 comprehensive tests covering all BLoC functionality - All tests passing (70/70) - Fixed linting issues and updated deprecated APIs - Improved code organization and maintainability
124 lines
3.9 KiB
Dart
124 lines
3.9 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:bookshelf_flutter/bloc/library/library_bloc.dart';
|
|
import 'package:bookshelf_flutter/bloc/library/library_event.dart';
|
|
import 'package:bookshelf_flutter/bloc/library/library_state.dart';
|
|
import 'package:bookshelf_flutter/models/models.dart';
|
|
|
|
void main() {
|
|
group('LibraryBloc', () {
|
|
late LibraryBloc libraryBloc;
|
|
|
|
setUp(() {
|
|
libraryBloc = LibraryBloc();
|
|
});
|
|
|
|
tearDown(() {
|
|
libraryBloc.close();
|
|
});
|
|
|
|
test('initial state is LibraryState.initial()', () {
|
|
expect(libraryBloc.state, isA<LibraryState>());
|
|
expect(libraryBloc.state.isLoading, true);
|
|
});
|
|
|
|
group('LoadBooks', () {
|
|
test('emits [LibraryState] with books when LoadBooks is added', () async {
|
|
final expected = [
|
|
isA<LibraryState>()
|
|
.having((state) => state.isLoading, 'isLoading', false)
|
|
.having((state) => state.books.isNotEmpty, 'books.isNotEmpty', true),
|
|
];
|
|
|
|
expectLater(libraryBloc.stream, emitsInOrder(expected));
|
|
|
|
libraryBloc.add(const LoadBooks());
|
|
});
|
|
});
|
|
|
|
group('SearchBooks', () {
|
|
test('filters books by title', () async {
|
|
libraryBloc.add(const LoadBooks());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
libraryBloc.add(const SearchBooks('Гэтсби'));
|
|
await Future.delayed(Duration.zero);
|
|
|
|
expect(libraryBloc.state.filteredBooks.length, 1);
|
|
expect(libraryBloc.state.filteredBooks.first.title, contains('Гэтсби'));
|
|
});
|
|
|
|
test('filters books by author', () async {
|
|
libraryBloc.add(const LoadBooks());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
libraryBloc.add(const SearchBooks('Оруэлл'));
|
|
await Future.delayed(Duration.zero);
|
|
|
|
expect(libraryBloc.state.filteredBooks.length, 1);
|
|
expect(libraryBloc.state.filteredBooks.first.author, contains('Оруэлл'));
|
|
});
|
|
|
|
test('filters books by genre', () async {
|
|
libraryBloc.add(const LoadBooks());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
libraryBloc.add(const SearchBooks('Fantasy'));
|
|
await Future.delayed(Duration.zero);
|
|
|
|
expect(libraryBloc.state.filteredBooks.isNotEmpty, true);
|
|
});
|
|
|
|
test('returns empty list when no matches found', () async {
|
|
libraryBloc.add(const LoadBooks());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
libraryBloc.add(const SearchBooks('NonExistent'));
|
|
await Future.delayed(Duration.zero);
|
|
|
|
expect(libraryBloc.state.filteredBooks.length, 0);
|
|
});
|
|
});
|
|
|
|
group('BookSelected', () {
|
|
test('updates selectedBook in state', () async {
|
|
libraryBloc.add(const LoadBooks());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
final book = libraryBloc.state.books.first;
|
|
libraryBloc.add(BookSelected(book));
|
|
await Future.delayed(Duration.zero);
|
|
|
|
expect(libraryBloc.state.selectedBook?.id, book.id);
|
|
});
|
|
});
|
|
|
|
group('FilterByStatus', () {
|
|
test('filters books by status', () async {
|
|
libraryBloc.add(const LoadBooks());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
libraryBloc.add(const FilterByStatus(BookStatus.reading));
|
|
await Future.delayed(Duration.zero);
|
|
|
|
expect(libraryBloc.state.filteredBooks.every((book) => book.status == BookStatus.reading), true);
|
|
expect(libraryBloc.state.statusFilter, BookStatus.reading);
|
|
});
|
|
});
|
|
|
|
group('ClearFilters', () {
|
|
test('clears search query and shows all books', () async {
|
|
libraryBloc.add(const LoadBooks());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
libraryBloc.add(const SearchBooks('test'));
|
|
await Future.delayed(Duration.zero);
|
|
|
|
libraryBloc.add(const ClearFilters());
|
|
await Future.delayed(Duration.zero);
|
|
|
|
expect(libraryBloc.state.searchQuery, '');
|
|
expect(libraryBloc.state.filteredBooks.length, libraryBloc.state.books.length);
|
|
});
|
|
});
|
|
});
|
|
} |