refactor: create separate BLoCs for each screen with comprehensive tests
- 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
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:bookshelf_flutter/bloc/book_details/book_details_bloc.dart';
|
||||
import 'package:bookshelf_flutter/bloc/book_details/book_details_event.dart';
|
||||
import 'package:bookshelf_flutter/bloc/book_details/book_details_state.dart';
|
||||
import 'package:bookshelf_flutter/models/models.dart';
|
||||
|
||||
void main() {
|
||||
group('BookDetailsBloc', () {
|
||||
late BookDetailsBloc bookDetailsBloc;
|
||||
late Book testBook;
|
||||
|
||||
setUp(() {
|
||||
bookDetailsBloc = BookDetailsBloc();
|
||||
testBook = createBook(
|
||||
id: '1',
|
||||
title: 'Test Book',
|
||||
author: 'Test Author',
|
||||
genre: 'Test Genre',
|
||||
annotation: 'Test annotation',
|
||||
coverUrl: 'https://example.com/cover.jpg',
|
||||
pages: 200,
|
||||
language: 'English',
|
||||
publishedYear: 2020,
|
||||
rating: 4.5,
|
||||
status: BookStatus.reading,
|
||||
progress: 50,
|
||||
isFavorite: false,
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
bookDetailsBloc.close();
|
||||
});
|
||||
|
||||
test('initial state is BookDetailsState.initial()', () {
|
||||
expect(bookDetailsBloc.state, isA<BookDetailsState>());
|
||||
expect(bookDetailsBloc.state.isLoading, true);
|
||||
});
|
||||
|
||||
group('LoadBookDetails', () {
|
||||
test('loads book details into state', () async {
|
||||
bookDetailsBloc.add(LoadBookDetails(testBook));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.id, testBook.id);
|
||||
expect(bookDetailsBloc.state.book?.title, testBook.title);
|
||||
expect(bookDetailsBloc.state.isLoading, false);
|
||||
});
|
||||
});
|
||||
|
||||
group('ToggleFavorite', () {
|
||||
test('toggles isFavorite from false to true', () async {
|
||||
bookDetailsBloc.add(LoadBookDetails(testBook));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
bookDetailsBloc.add(const ToggleFavorite());
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.isFavorite, true);
|
||||
});
|
||||
|
||||
test('toggles isFavorite from true to false', () async {
|
||||
final favoriteBook = testBook.copyWith(isFavorite: true);
|
||||
bookDetailsBloc.add(LoadBookDetails(favoriteBook));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
bookDetailsBloc.add(const ToggleFavorite());
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.isFavorite, false);
|
||||
});
|
||||
|
||||
test('does nothing when no book is loaded', () async {
|
||||
final initialFavorite = bookDetailsBloc.state.book?.isFavorite;
|
||||
bookDetailsBloc.add(const ToggleFavorite());
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.isFavorite, initialFavorite);
|
||||
});
|
||||
});
|
||||
|
||||
group('UpdateProgress', () {
|
||||
test('updates progress and keeps reading status', () async {
|
||||
bookDetailsBloc.add(LoadBookDetails(testBook));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
bookDetailsBloc.add(const UpdateProgress(75));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.progress, 75);
|
||||
expect(bookDetailsBloc.state.book?.status, BookStatus.reading);
|
||||
});
|
||||
|
||||
test('updates status to done when progress is 100', () async {
|
||||
bookDetailsBloc.add(LoadBookDetails(testBook));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
bookDetailsBloc.add(const UpdateProgress(100));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.progress, 100);
|
||||
expect(bookDetailsBloc.state.book?.status, BookStatus.done);
|
||||
});
|
||||
|
||||
test('does nothing when no book is loaded', () async {
|
||||
final initialProgress = bookDetailsBloc.state.book?.progress;
|
||||
bookDetailsBloc.add(const UpdateProgress(50));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.progress, initialProgress);
|
||||
});
|
||||
});
|
||||
|
||||
group('UpdateStatus', () {
|
||||
test('updates book status', () async {
|
||||
bookDetailsBloc.add(LoadBookDetails(testBook));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
bookDetailsBloc.add(const UpdateStatus(BookStatus.done));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.book?.status, BookStatus.done);
|
||||
});
|
||||
});
|
||||
|
||||
group('DeleteBook', () {
|
||||
test('sets isDeleted to true', () async {
|
||||
bookDetailsBloc.add(LoadBookDetails(testBook));
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
bookDetailsBloc.add(const DeleteBook());
|
||||
await Future.delayed(Duration.zero);
|
||||
|
||||
expect(bookDetailsBloc.state.isDeleted, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user