Skip to content

Commit

Permalink
Merge pull request #6 from Blockchain-Country/toggle
Browse files Browse the repository at this point in the history
added toggle favorite functionality and covered with unit tests
  • Loading branch information
Blockchain-Country authored Oct 24, 2024
2 parents 69a3e84 + ecdefe6 commit f827382
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 7 deletions.
37 changes: 34 additions & 3 deletions package-lock.json

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

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-redux": "^9.1.2",
"react-scripts": "5.0.1",
"uuid": "^10.0.0",
Expand Down Expand Up @@ -37,5 +38,8 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11"
}
}
29 changes: 26 additions & 3 deletions src/components/bookList/BookList.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import { useDispatch, useSelector } from 'react-redux'
import { TbStar } from 'react-icons/tb'
import { TbStarFilled } from 'react-icons/tb'
import {
selectBook,
deleteBook,
toggleFavorite,
} from '../../redux/slices/BooksSlice'
import './BookList.css'
import { selectBook } from '../../redux/slices/BooksSlice'
import { deleteBook } from '../../redux/slices/BooksSlice'

const BookList = () => {
const books = useSelector(selectBook)
const dispatch = useDispatch()

const handleDeleteBook = (id) => {
dispatch(deleteBook(id))
books.forEach((book) => {
if (book.id === id && !book.isFavorite) {
dispatch(deleteBook(id))
}
})
}

const toggleFavoriteBook = (id) => {
dispatch(toggleFavorite(id))
}

return (
Expand All @@ -30,6 +43,16 @@ const BookList = () => {
</span>
</div>
<div className="book-actions">
<span
onClick={() => toggleFavoriteBook(book.id)}
data-testid={`isFavorite_${book.isFavorite}`}
>
{book.isFavorite ? (
<TbStarFilled className="star-icon" />
) : (
<TbStar className="star-icon" />
)}
</span>
<button
onClick={() => handleDeleteBook(book.id)}
data-testid="delete_book_btn"
Expand Down
42 changes: 42 additions & 0 deletions src/components/bookList/BookList.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,46 @@ describe('BookList Component Tests', () => {
const noBooksSign = within(container).getByTestId('no_books_sign')
expect(noBooksSign).toBeInTheDocument()
})

test('Should not able to delete Favorite book', () => {
const mockedStore = createStore({
books: [
{
title: bookTitleName,
author: bookAuthorName,
id: bookId,
isFavorite: false,
},
],
})

const { container } = setup(BookList, mockedStore)

const bookItems = within(container).getByTestId(bookId)
let isFavoriteFalse = within(bookItems).getByTestId('isFavorite_false')
expect(isFavoriteFalse).toBeInTheDocument()

fireEvent.click(isFavoriteFalse)
let isFavoriteTrue = within(bookItems).getByTestId('isFavorite_true')
expect(isFavoriteTrue).toBeInTheDocument()

//try to delete toggled book:
let deleteBookBtn = within(bookItems).getByTestId('delete_book_btn')
fireEvent.click(deleteBookBtn)
expect(bookItems).toBeInTheDocument()

//untoggle favorite:
isFavoriteTrue = within(bookItems).getByTestId('isFavorite_true')
fireEvent.click(isFavoriteTrue)
isFavoriteFalse = within(bookItems).getByTestId('isFavorite_false')
expect(isFavoriteFalse).toBeInTheDocument()

//delete book:
deleteBookBtn = within(bookItems).getByTestId('delete_book_btn')
fireEvent.click(deleteBookBtn)

//assert if the book deleted from the DOM:
const deletedBookItem = within(container).queryByTestId(bookId)
expect(deletedBookItem).toBeNull()
})
})
9 changes: 8 additions & 1 deletion src/redux/slices/BooksSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@ const booksSlice = createSlice({
deleteBook: (state, action) => {
return state.filter((book) => book.id !== action.payload)
},
toggleFavorite: (state, action) => {
state.forEach((book) => {
if (book.id === action.payload) {
book.isFavorite = !book.isFavorite
}
})
},
},
})

export const { addBook, deleteBook } = booksSlice.actions
export const { addBook, deleteBook, toggleFavorite } = booksSlice.actions

export const selectBook = (state) => state.books

Expand Down
1 change: 1 addition & 0 deletions src/utils/createBook.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const createBook = (book) => {
return {
...book,
id: uuidv4(),
isFavorite: false,
}
}

Expand Down

0 comments on commit f827382

Please sign in to comment.