Fix import paths and test issues

- Fixed test file import paths to point to correct Bloc file locations
- Fixed Bloc file import paths for models (../../../models/models.dart)
- Added explicit type annotations to resolve null safety warnings
- Fixed null safety issues in wishlist_bloc_test.dart
- All 70 tests now passing
This commit is contained in:
Yuriy Panov
2026-02-04 15:28:59 +06:00
parent 310463e89a
commit 2f97873095
46 changed files with 270 additions and 260 deletions

View File

@@ -2,9 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import '../bloc/app_bloc.dart'; import '../../bloc/app_bloc.dart';
import '../bloc/app_event.dart'; import '../../bloc/app_event.dart';
import '../models/models.dart'; import '../../../models/models.dart';
class AddBookScreen extends StatefulWidget { class AddBookScreen extends StatefulWidget {
final dynamic initialData; final dynamic initialData;

View File

@@ -1,5 +1,5 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
import 'add_book_event.dart'; import 'add_book_event.dart';
import 'add_book_state.dart'; import 'add_book_state.dart';

View File

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
class AddBookState extends Equatable { class AddBookState extends Equatable {
final String title; final String title;

View File

@@ -1,5 +1,5 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
import 'book_details_event.dart'; import 'book_details_event.dart';
import 'book_details_state.dart'; import 'book_details_state.dart';

View File

@@ -1,4 +1,4 @@
import '../../models/models.dart'; import '../../../models/models.dart';
abstract class BookDetailsEvent { abstract class BookDetailsEvent {
const BookDetailsEvent(); const BookDetailsEvent();

View File

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
class BookDetailsState extends Equatable { class BookDetailsState extends Equatable {
final Book? book; final Book? book;

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import '../bloc/app_bloc.dart'; import '../../bloc/app_bloc.dart';
import '../bloc/app_event.dart'; import '../../bloc/app_event.dart';
import '../models/models.dart'; import '../../../models/models.dart';
class BookDetailsScreen extends StatelessWidget { class BookDetailsScreen extends StatelessWidget {
final Book book; final Book book;

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
import 'categories_event.dart'; import 'categories_event.dart';
import 'categories_state.dart'; import 'categories_state.dart';

View File

@@ -1,4 +1,4 @@
import '../../models/models.dart'; import '../../../models/models.dart';
abstract class CategoriesEvent { abstract class CategoriesEvent {
const CategoriesEvent(); const CategoriesEvent();

View File

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
class CategoriesState extends Equatable { class CategoriesState extends Equatable {
final List<Category> categories; final List<Category> categories;

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../models/models.dart'; import '../../../models/models.dart';
class CategoriesScreen extends StatelessWidget { class CategoriesScreen extends StatelessWidget {
const CategoriesScreen({super.key}); const CategoriesScreen({super.key});

View File

@@ -1,5 +1,5 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
import 'home_event.dart'; import 'home_event.dart';
import 'home_state.dart'; import 'home_state.dart';

View File

@@ -1,4 +1,4 @@
import '../../models/models.dart'; import '../../../models/models.dart';
abstract class HomeEvent { abstract class HomeEvent {
const HomeEvent(); const HomeEvent();

View File

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
class HomeState extends Equatable { class HomeState extends Equatable {
final AppScreen currentScreen; final AppScreen currentScreen;

View File

@@ -1,16 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../bloc/app_bloc.dart'; import '../../bloc/app_bloc.dart';
import '../bloc/app_state.dart'; import '../../bloc/app_state.dart';
import '../models/models.dart'; import '../../../models/models.dart';
import 'library_screen.dart'; import '../library/library_screen.dart';
import 'categories_screen.dart'; import '../categories/categories_screen.dart';
import 'book_details_screen.dart'; import '../book_details/book_details_screen.dart';
import 'add_book_screen.dart'; import '../add_book/add_book_screen.dart';
import 'scanner_screen.dart'; import '../scanner/scanner_screen.dart';
import 'wishlist_screen.dart'; import '../wishlist/wishlist_screen.dart';
import 'settings_screen.dart'; import '../settings/settings_screen.dart';
import '../widgets/bottom_nav.dart'; import '../../widgets/bottom_nav.dart';
class HomeScreen extends StatelessWidget { class HomeScreen extends StatelessWidget {
const HomeScreen({super.key}); const HomeScreen({super.key});

View File

@@ -1,5 +1,5 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
import 'library_event.dart'; import 'library_event.dart';
import 'library_state.dart'; import 'library_state.dart';
@@ -87,7 +87,7 @@ class LibraryBloc extends Bloc<LibraryEvent, LibraryState> {
void _onSearchBooks(SearchBooks event, Emitter<LibraryState> emit) { void _onSearchBooks(SearchBooks event, Emitter<LibraryState> emit) {
final query = event.query.toLowerCase(); final query = event.query.toLowerCase();
final filtered = state.books.where((book) { final filtered = state.books.where((Book book) {
return book.title.toLowerCase().contains(query) || return book.title.toLowerCase().contains(query) ||
book.author.toLowerCase().contains(query) || book.author.toLowerCase().contains(query) ||
book.genre.toLowerCase().contains(query); book.genre.toLowerCase().contains(query);
@@ -104,7 +104,7 @@ class LibraryBloc extends Bloc<LibraryEvent, LibraryState> {
} }
void _onFilterByStatus(FilterByStatus event, Emitter<LibraryState> emit) { void _onFilterByStatus(FilterByStatus event, Emitter<LibraryState> emit) {
final filtered = state.books.where((book) { final filtered = state.books.where((Book book) {
return book.status == event.status; return book.status == event.status;
}).toList(); }).toList();

View File

@@ -1,4 +1,4 @@
import '../../models/models.dart'; import '../../../models/models.dart';
abstract class LibraryEvent { abstract class LibraryEvent {
const LibraryEvent(); const LibraryEvent();

View File

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
class LibraryState extends Equatable { class LibraryState extends Equatable {
final List<Book> books; final List<Book> books;

View File

@@ -1,10 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import '../bloc/app_bloc.dart'; import '../../bloc/app_bloc.dart';
import '../bloc/app_event.dart'; import '../../bloc/app_event.dart';
import '../bloc/app_state.dart'; import '../../bloc/app_state.dart';
import '../models/models.dart'; import '../../../models/models.dart';
class LibraryScreen extends StatefulWidget { class LibraryScreen extends StatefulWidget {
const LibraryScreen({super.key}); const LibraryScreen({super.key});

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../bloc/app_bloc.dart'; import '../../bloc/app_bloc.dart';
import '../bloc/app_event.dart'; import '../../bloc/app_event.dart';
import '../models/models.dart'; import '../../../models/models.dart';
class ScannerScreen extends StatelessWidget { class ScannerScreen extends StatelessWidget {
const ScannerScreen({super.key}); const ScannerScreen({super.key});

View File

@@ -1,5 +1,5 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
import 'wishlist_event.dart'; import 'wishlist_event.dart';
import 'wishlist_state.dart'; import 'wishlist_state.dart';

View File

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import '../../models/models.dart'; import '../../../models/models.dart';
class WishlistState extends Equatable { class WishlistState extends Equatable {
final List<Book> books; final List<Book> books;

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/app_bloc.dart'; import 'bloc/app_bloc.dart';
import 'screens/home_screen.dart'; import 'features/home/home_screen.dart';
void main() { void main() {
runApp(const BookshelfApp()); runApp(const BookshelfApp());

View File

@@ -0,0 +1,10 @@
// App screen enum
enum AppScreen {
library,
categories,
wishlist,
settings,
details,
addBook,
scanner,
}

View File

@@ -0,0 +1,127 @@
import 'book_status.dart';
// Book record - using Dart records as data classes
typedef Book = ({
String id,
String title,
String author,
String genre,
String annotation,
String? coverUrl,
int? pages,
String? language,
int? publishedYear,
double? rating,
BookStatus status,
int? progress,
bool isFavorite,
});
// Helper function to create a Book record
Book createBook({
required String id,
required String title,
required String author,
required String genre,
required String annotation,
String? coverUrl,
int? pages,
String? language,
int? publishedYear,
double? rating,
required BookStatus status,
int? progress,
required bool isFavorite,
}) {
return (
id: id,
title: title,
author: author,
genre: genre,
annotation: annotation,
coverUrl: coverUrl,
pages: pages,
language: language,
publishedYear: publishedYear,
rating: rating,
status: status,
progress: progress,
isFavorite: isFavorite,
);
}
// Extension to create Book from partial data
extension BookExtension on Book {
Book copyWith({
String? id,
String? title,
String? author,
String? genre,
String? annotation,
String? coverUrl,
int? pages,
String? language,
int? publishedYear,
double? rating,
BookStatus? status,
int? progress,
bool? isFavorite,
}) {
return createBook(
id: id ?? this.id,
title: title ?? this.title,
author: author ?? this.author,
genre: genre ?? this.genre,
annotation: annotation ?? this.annotation,
coverUrl: coverUrl ?? this.coverUrl,
pages: pages ?? this.pages,
language: language ?? this.language,
publishedYear: publishedYear ?? this.publishedYear,
rating: rating ?? this.rating,
status: status ?? this.status,
progress: progress ?? this.progress,
isFavorite: isFavorite ?? this.isFavorite,
);
}
// Convert to JSON for storage/transport
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'author': author,
'genre': genre,
'annotation': annotation,
'coverUrl': coverUrl,
'pages': pages,
'language': language,
'publishedYear': publishedYear,
'rating': rating,
'status': status.name,
'progress': progress,
'isFavorite': isFavorite,
};
}
// Create Book from JSON
static Book fromJson(Map<String, dynamic> json) {
return (
id: json['id'] as String,
title: json['title'] as String,
author: json['author'] as String,
genre: json['genre'] as String,
annotation: json['annotation'] as String,
coverUrl: json['coverUrl'] as String?,
pages: json['pages'] as int?,
language: json['language'] as String?,
publishedYear: json['publishedYear'] as int?,
rating: (json['rating'] as num?)?.toDouble(),
status: BookStatus.values.firstWhere(
(e) => e.name == json['status'],
orElse: () => BookStatus.wantToRead,
),
progress: json['progress'] as int?,
isFavorite: json['isFavorite'] as bool? ?? false,
);
}
}

View File

@@ -0,0 +1,20 @@
// Book status enum
enum BookStatus {
reading,
done,
wantToRead,
}
// Extension for BookStatus to get display name
extension BookStatusExtension on BookStatus {
String get displayName {
switch (this) {
case BookStatus.reading:
return 'Reading Now';
case BookStatus.done:
return 'Completed';
case BookStatus.wantToRead:
return 'Wishlist';
}
}
}

View File

@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
// Category record - using Dart records as data classes
typedef Category = ({
String id,
String name,
int count,
IconData icon,
String colorClass,
});
// Helper function to create a Category record
Category createCategory({
required String id,
required String name,
required int count,
required IconData icon,
required String colorClass,
}) {
return (
id: id,
name: name,
count: count,
icon: icon,
colorClass: colorClass,
);
}

View File

@@ -1,185 +1,5 @@
import 'package:flutter/material.dart'; // Barrel export for all models
export 'app_screen.dart';
// App screen enum export 'book_status.dart';
enum AppScreen { export 'category.dart';
library, export 'book.dart';
categories,
wishlist,
settings,
details,
addBook,
scanner,
}
// Book status enum
enum BookStatus {
reading,
done,
wantToRead,
}
// Extension for BookStatus to get display name
extension BookStatusExtension on BookStatus {
String get displayName {
switch (this) {
case BookStatus.reading:
return 'Reading Now';
case BookStatus.done:
return 'Completed';
case BookStatus.wantToRead:
return 'Wishlist';
}
}
}
// Category record - using Dart records as data classes
typedef Category = ({
String id,
String name,
int count,
IconData icon,
String colorClass,
});
// Book record - using Dart records as data classes
typedef Book = ({
String id,
String title,
String author,
String genre,
String annotation,
String? coverUrl,
int? pages,
String? language,
int? publishedYear,
double? rating,
BookStatus status,
int? progress,
bool isFavorite,
});
// Helper function to create a Category record
Category createCategory({
required String id,
required String name,
required int count,
required IconData icon,
required String colorClass,
}) {
return (
id: id,
name: name,
count: count,
icon: icon,
colorClass: colorClass,
);
}
// Helper function to create a Book record
Book createBook({
required String id,
required String title,
required String author,
required String genre,
required String annotation,
String? coverUrl,
int? pages,
String? language,
int? publishedYear,
double? rating,
required BookStatus status,
int? progress,
required bool isFavorite,
}) {
return (
id: id,
title: title,
author: author,
genre: genre,
annotation: annotation,
coverUrl: coverUrl,
pages: pages,
language: language,
publishedYear: publishedYear,
rating: rating,
status: status,
progress: progress,
isFavorite: isFavorite,
);
}
// Extension to create Book from partial data
extension BookExtension on Book {
Book copyWith({
String? id,
String? title,
String? author,
String? genre,
String? annotation,
String? coverUrl,
int? pages,
String? language,
int? publishedYear,
double? rating,
BookStatus? status,
int? progress,
bool? isFavorite,
}) {
return createBook(
id: id ?? this.id,
title: title ?? this.title,
author: author ?? this.author,
genre: genre ?? this.genre,
annotation: annotation ?? this.annotation,
coverUrl: coverUrl ?? this.coverUrl,
pages: pages ?? this.pages,
language: language ?? this.language,
publishedYear: publishedYear ?? this.publishedYear,
rating: rating ?? this.rating,
status: status ?? this.status,
progress: progress ?? this.progress,
isFavorite: isFavorite ?? this.isFavorite,
);
}
// Convert to JSON for storage/transport
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'author': author,
'genre': genre,
'annotation': annotation,
'coverUrl': coverUrl,
'pages': pages,
'language': language,
'publishedYear': publishedYear,
'rating': rating,
'status': status.name,
'progress': progress,
'isFavorite': isFavorite,
};
}
// Create Book from JSON
static Book fromJson(Map<String, dynamic> json) {
return (
id: json['id'] as String,
title: json['title'] as String,
author: json['author'] as String,
genre: json['genre'] as String,
annotation: json['annotation'] as String,
coverUrl: json['coverUrl'] as String?,
pages: json['pages'] as int?,
language: json['language'] as String?,
publishedYear: json['publishedYear'] as int?,
rating: (json['rating'] as num?)?.toDouble(),
status: BookStatus.values.firstWhere(
(e) => e.name == json['status'],
orElse: () => BookStatus.wantToRead,
),
progress: json['progress'] as int?,
isFavorite: json['isFavorite'] as bool? ?? false,
);
}
}

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/add_book/add_book_bloc.dart'; import 'package:bookshelf_flutter/features/add_book/bloc/add_book_bloc.dart';
import 'package:bookshelf_flutter/bloc/add_book/add_book_event.dart'; import 'package:bookshelf_flutter/features/add_book/bloc/add_book_event.dart';
import 'package:bookshelf_flutter/bloc/add_book/add_book_state.dart'; import 'package:bookshelf_flutter/features/add_book/bloc/add_book_state.dart';
import 'package:bookshelf_flutter/models/models.dart'; import 'package:bookshelf_flutter/models/models.dart';
void main() { void main() {

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/book_details/book_details_bloc.dart'; import 'package:bookshelf_flutter/features/book_details/bloc/book_details_bloc.dart';
import 'package:bookshelf_flutter/bloc/book_details/book_details_event.dart'; import 'package:bookshelf_flutter/features/book_details/bloc/book_details_event.dart';
import 'package:bookshelf_flutter/bloc/book_details/book_details_state.dart'; import 'package:bookshelf_flutter/features/book_details/bloc/book_details_state.dart';
import 'package:bookshelf_flutter/models/models.dart'; import 'package:bookshelf_flutter/models/models.dart';
void main() { void main() {

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/categories/categories_bloc.dart'; import 'package:bookshelf_flutter/features/categories/bloc/categories_bloc.dart';
import 'package:bookshelf_flutter/bloc/categories/categories_event.dart'; import 'package:bookshelf_flutter/features/categories/bloc/categories_event.dart';
import 'package:bookshelf_flutter/bloc/categories/categories_state.dart'; import 'package:bookshelf_flutter/features/categories/bloc/categories_state.dart';
void main() { void main() {
group('CategoriesBloc', () { group('CategoriesBloc', () {

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/home/home_bloc.dart'; import 'package:bookshelf_flutter/features/home/bloc/home_bloc.dart';
import 'package:bookshelf_flutter/bloc/home/home_event.dart'; import 'package:bookshelf_flutter/features/home/bloc/home_event.dart';
import 'package:bookshelf_flutter/bloc/home/home_state.dart'; import 'package:bookshelf_flutter/features/home/bloc/home_state.dart';
import 'package:bookshelf_flutter/models/models.dart'; import 'package:bookshelf_flutter/models/models.dart';
void main() { void main() {

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/library/library_bloc.dart'; import 'package:bookshelf_flutter/features/library/bloc/library_bloc.dart';
import 'package:bookshelf_flutter/bloc/library/library_event.dart'; import 'package:bookshelf_flutter/features/library/bloc/library_event.dart';
import 'package:bookshelf_flutter/bloc/library/library_state.dart'; import 'package:bookshelf_flutter/features/library/bloc/library_state.dart';
import 'package:bookshelf_flutter/models/models.dart'; import 'package:bookshelf_flutter/models/models.dart';
void main() { void main() {
@@ -100,7 +100,7 @@ void main() {
libraryBloc.add(const FilterByStatus(BookStatus.reading)); libraryBloc.add(const FilterByStatus(BookStatus.reading));
await Future.delayed(Duration.zero); await Future.delayed(Duration.zero);
expect(libraryBloc.state.filteredBooks.every((book) => book.status == BookStatus.reading), true); expect(libraryBloc.state.filteredBooks.every((Book book) => book.status == BookStatus.reading), true);
expect(libraryBloc.state.statusFilter, BookStatus.reading); expect(libraryBloc.state.statusFilter, BookStatus.reading);
}); });
}); });

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/scanner/scanner_bloc.dart'; import 'package:bookshelf_flutter/features/scanner/bloc/scanner_bloc.dart';
import 'package:bookshelf_flutter/bloc/scanner/scanner_event.dart'; import 'package:bookshelf_flutter/features/scanner/bloc/scanner_event.dart';
import 'package:bookshelf_flutter/bloc/scanner/scanner_state.dart'; import 'package:bookshelf_flutter/features/scanner/bloc/scanner_state.dart';
void main() { void main() {
group('ScannerBloc', () { group('ScannerBloc', () {

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/settings/settings_bloc.dart'; import 'package:bookshelf_flutter/features/settings/bloc/settings_bloc.dart';
import 'package:bookshelf_flutter/bloc/settings/settings_event.dart'; import 'package:bookshelf_flutter/features/settings/bloc/settings_event.dart';
import 'package:bookshelf_flutter/bloc/settings/settings_state.dart'; import 'package:bookshelf_flutter/features/settings/bloc/settings_state.dart';
void main() { void main() {
group('SettingsBloc', () { group('SettingsBloc', () {

View File

@@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:bookshelf_flutter/bloc/wishlist/wishlist_bloc.dart'; import 'package:bookshelf_flutter/features/wishlist/bloc/wishlist_bloc.dart';
import 'package:bookshelf_flutter/bloc/wishlist/wishlist_event.dart'; import 'package:bookshelf_flutter/features/wishlist/bloc/wishlist_event.dart';
import 'package:bookshelf_flutter/bloc/wishlist/wishlist_state.dart'; import 'package:bookshelf_flutter/features/wishlist/bloc/wishlist_state.dart';
import 'package:bookshelf_flutter/models/models.dart'; import 'package:bookshelf_flutter/models/models.dart';
void main() { void main() {
@@ -37,16 +37,19 @@ void main() {
wishlistBloc.add(const LoadWishlist()); wishlistBloc.add(const LoadWishlist());
await Future.delayed(Duration.zero); await Future.delayed(Duration.zero);
final bookId = wishlistBloc.state.books.first.id; expect(wishlistBloc.state.books.isNotEmpty, true, reason: 'No books loaded');
final book = wishlistBloc.state.books.first;
final bookId = book.id;
wishlistBloc.add(RemoveFromWishlist(bookId)); wishlistBloc.add(RemoveFromWishlist(bookId));
await Future.delayed(Duration.zero); await Future.delayed(Duration.zero);
expect( expect(
wishlistBloc.state.books.any((book) => book.id == bookId), wishlistBloc.state.books.any((b) => b.id == bookId),
false, false,
); );
expect( expect(
wishlistBloc.state.filteredBooks.any((book) => book.id == bookId), wishlistBloc.state.filteredBooks.any((b) => b.id == bookId),
false, false,
); );
}); });
@@ -91,12 +94,15 @@ void main() {
wishlistBloc.add(const LoadWishlist()); wishlistBloc.add(const LoadWishlist());
await Future.delayed(Duration.zero); await Future.delayed(Duration.zero);
final bookId = wishlistBloc.state.books.first.id; expect(wishlistBloc.state.books.isNotEmpty, true, reason: 'No books loaded');
final book = wishlistBloc.state.books.first;
final bookId = book.id;
wishlistBloc.add(MoveToLibrary(bookId)); wishlistBloc.add(MoveToLibrary(bookId));
await Future.delayed(Duration.zero); await Future.delayed(Duration.zero);
final book = wishlistBloc.state.books.firstWhere((b) => b.id == bookId); final foundBook = wishlistBloc.state.books.firstWhere((b) => b.id == bookId);
expect(book.status, BookStatus.reading); expect(foundBook.status, BookStatus.reading);
expect(wishlistBloc.state.movedBookId, bookId); expect(wishlistBloc.state.movedBookId, bookId);
}); });
}); });