Skip to content

Commit e6601c8

Browse files
authored
Merge pull request #164 from saseungmin/delete-own-study-review
[Feature] Add delete my study review logic
2 parents 929cf3a + a449b6e commit e6601c8

File tree

18 files changed

+18970
-72
lines changed

18 files changed

+18970
-72
lines changed

package-lock.json

Lines changed: 18675 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"@babel/core": "^7.12.3",
6161
"@babel/preset-env": "^7.12.1",
6262
"@babel/preset-react": "^7.12.5",
63+
"@svgr/webpack": "^5.5.0",
6364
"@testing-library/jest-dom": "^5.11.6",
6465
"@testing-library/react": "^11.1.2",
6566
"@types/jest": "^26.0.15",

src/__mocks__/firebase/app.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const firebase = jest.genMockFromModule('firebase/app');
2+
3+
firebase.firestore = jest.fn().mockImplementation(() => ({
4+
collection: jest.fn().mockImplementation(() => ({
5+
doc: jest.fn().mockImplementation(() => ({
6+
update: jest.fn(),
7+
delete: jest.fn(),
8+
})),
9+
})),
10+
}));
11+
12+
firebase.auth = jest.fn().mockImplementation(() => ({}));
13+
14+
export default firebase;
File renamed without changes.

src/assets/icons/close.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/introduce/Review.jsx

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import palette from '../../styles/palette';
1010

1111
import { changeDateToTime } from '../../util/utils';
1212

13+
import CloseSvg from '../../assets/icons/close.svg';
14+
1315
const ReviewWrapper = styled.div`
1416
background-color: #f8f8f8;
1517
display: flex;
@@ -33,22 +35,46 @@ const ReviewContentInfo = styled.div`
3335
justify-content: space-between;
3436
`;
3537

36-
const Review = ({ review }) => {
38+
const ReviewHeader = styled.div`
39+
display: flex;
40+
justify-content: space-between;
41+
align-items: center;
42+
`;
43+
44+
const CloseIcon = styled(CloseSvg)`
45+
cursor: pointer;
46+
width: 20px;
47+
height: 20px;
48+
fill: ${palette.gray[6]};
49+
transition: fill .2s;
50+
51+
&:hover {
52+
fill: ${palette.gray[8]};
53+
}
54+
`;
55+
56+
const Review = ({ user, review, onClick }) => {
3757
const {
3858
id, rating, content, createDate,
3959
} = review;
4060

4161
return (
4262
<ReviewWrapper>
43-
<StarRatings
44-
rating={rating}
45-
starRatedColor="#ffc816"
46-
numberOfStars={5}
47-
starDimension="20px"
48-
starSpacing="0"
49-
starHoverColor="#ffc816"
50-
name="rating"
51-
/>
63+
<ReviewHeader>
64+
<StarRatings
65+
rating={rating}
66+
starRatedColor="#ffc816"
67+
numberOfStars={5}
68+
starDimension="20px"
69+
starSpacing="0"
70+
/>
71+
{user === id && (
72+
<CloseIcon
73+
data-testid="close-icon"
74+
onClick={() => onClick(id)}
75+
/>
76+
)}
77+
</ReviewHeader>
5278
<ReviewContent>
5379
{content}
5480
</ReviewContent>
Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22

3-
import { render } from '@testing-library/react';
3+
import { render, fireEvent } from '@testing-library/react';
44

55
import Review from './Review';
66

@@ -12,16 +12,44 @@ describe('Review', () => {
1212
createDate: new Date(),
1313
};
1414

15+
const handleClick = jest.fn();
16+
1517
const renderReview = (review) => render((
1618
<Review
19+
user={given.user}
1720
review={review}
21+
onClick={handleClick}
1822
/>
1923
));
2024

21-
it('Render review contents', () => {
22-
const { container } = renderReview(mockReview);
25+
context("When it's my review", () => {
26+
given('user', () => ('test@test.com'));
27+
28+
it('Render review contents', () => {
29+
const { container, getByTestId } = renderReview(mockReview);
30+
31+
expect(container).toHaveTextContent('review');
32+
expect(container).toHaveTextContent('test@test.com');
33+
expect(getByTestId('close-icon')).not.toBeNull();
34+
});
35+
36+
it('Listen delete click events', () => {
37+
const { getByTestId } = renderReview(mockReview);
38+
39+
fireEvent.click(getByTestId('close-icon'));
40+
41+
expect(handleClick).toBeCalledTimes(1);
42+
});
43+
});
44+
45+
context("When it's my review", () => {
46+
given('user', () => ('test'));
47+
48+
it('Render review contents', () => {
49+
const { container } = renderReview(mockReview);
2350

24-
expect(container).toHaveTextContent('review');
25-
expect(container).toHaveTextContent('test@test.com');
51+
expect(container).toHaveTextContent('review');
52+
expect(container).toHaveTextContent('test@test.com');
53+
});
2654
});
2755
});

src/components/introduce/ReviewList.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const EmptyReviewWrapper = styled.div`
2727
border-radius: 5px;
2828
`;
2929

30-
const ReviewList = ({ reviews }) => {
30+
const ReviewList = ({ user, reviews, onDelete }) => {
3131
if (_.isEmpty(reviews)) {
3232
return (
3333
<EmptyReviewWrapper>
@@ -44,7 +44,9 @@ const ReviewList = ({ reviews }) => {
4444
{reviews.map((review) => (
4545
<Review
4646
key={review.id}
47+
user={user}
4748
review={review}
49+
onClick={onDelete}
4850
/>
4951
))}
5052
</ReviewWrapper>

src/components/introduce/ReviewList.test.jsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22

3-
import { render } from '@testing-library/react';
3+
import { render, fireEvent } from '@testing-library/react';
44

55
import ReviewList from './ReviewList';
66

@@ -12,9 +12,13 @@ describe('ReviewList', () => {
1212
createdDate: new Date(),
1313
}];
1414

15+
const handleClick = jest.fn();
16+
1517
const renderReviewList = (reviews) => render((
1618
<ReviewList
19+
user="test@test.com"
1720
reviews={reviews}
21+
onDelete={handleClick}
1822
/>
1923
));
2024

@@ -27,6 +31,14 @@ describe('ReviewList', () => {
2731
expect(container).toHaveTextContent('review');
2832
expect(container).toHaveTextContent('test@test.com');
2933
});
34+
35+
it('Listen delete click events', () => {
36+
const { getByTestId } = renderReviewList(mockReviews);
37+
38+
fireEvent.click(getByTestId('close-icon'));
39+
40+
expect(handleClick).toBeCalledTimes(1);
41+
});
3042
});
3143

3244
context('Without reviews', () => {

src/containers/introduce/ReviewContainer.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useSelector, useDispatch } from 'react-redux';
66
import {
77
getAuth, getGroup, isCheckedTimeStatus, changeDateToTime,
88
} from '../../util/utils';
9-
import { changeStudyReviewFields, setStudyReview } from '../../reducers/groupSlice';
9+
import { changeStudyReviewFields, setStudyReview, deleteStudyReview } from '../../reducers/groupSlice';
1010

1111
import SubTitle from '../../styles/SubTitle';
1212

@@ -35,6 +35,10 @@ const ReviewFormContainer = () => {
3535
}));
3636
}, [dispatch, user, studyReviewFields]);
3737

38+
const onDeleteReview = useCallback((reviewId) => {
39+
dispatch(deleteStudyReview(reviewId));
40+
}, [dispatch]);
41+
3842
if (!group) {
3943
return null;
4044
}
@@ -63,7 +67,9 @@ const ReviewFormContainer = () => {
6367
onSubmit={onSubmitReview}
6468
/>
6569
<ReviewList
70+
user={user}
6671
reviews={group.reviews ? group.reviews : []}
72+
onDelete={onDeleteReview}
6773
/>
6874
</>
6975
);

0 commit comments

Comments
 (0)