-
Notifications
You must be signed in to change notification settings - Fork 155
[2단계 - 상세 정보 & UI/UX 개선하기] 찰리 미션 제출합니다. #292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: yuncic
Are you sure you want to change the base?
Changes from 54 commits
c256ca3
d51c3f2
0292b66
edc0811
1abceb5
32daaab
de28417
ae0d491
a316471
7f8b604
c8156ec
ee830e4
d21e1be
e743ebc
8da7434
5cd3817
74150b9
00b3354
b9d4435
1dcfc6a
9d9c9e3
5d5098f
df6e2ed
f281375
dd13f81
350ace7
011997c
f8e44f8
0ed101c
2f54796
0504185
b20fbd2
fdad549
8b4d0c6
2254261
c564d97
51249f1
856e62a
6127209
a56ffcf
fcbdab6
e03ba10
6d5ac60
4cb37f6
40af500
1d39687
1630e6a
959a082
dca0674
b49c1e1
e796c59
de26508
384a13f
1d6520e
517e398
f1d8509
5ad7506
97d46db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,8 @@ | ||
| { | ||
| "endOfLine": "auto", | ||
| "printWidth": 120, | ||
| "tabWidth": 4, | ||
| "singleQuote": true, | ||
| "trailingComma": "all", | ||
| "semi": false | ||
| "endOfLine": "auto", | ||
| "printWidth": 120, | ||
| "tabWidth": 4, | ||
| "singleQuote": true, | ||
| "trailingComma": "all", | ||
| "semi": true | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,32 +1,51 @@ | ||
| # javascript-movie-review | ||
|
|
||
| FE 레벨1 영화 리뷰 미션 | ||
| FE 레벨1 영화 리뷰 미션 step2 | ||
|
|
||
| ## 요구사항 명세서 | ||
|
|
||
| ### 영화 | ||
| ## 영화 상세정보 조회 모달 | ||
|
|
||
| - [x] 영화 리스트를 불러온다. | ||
| - [x] 영화 섹션 하나에 포스터, 평점, 영화 제목을 띄운다. | ||
| - [x] 영화 목록을 띄울 때 20개씩 띄운다. | ||
| - [x] 검색어에 따른 필러링된 영화 리스트를 불러온다. | ||
| ### 이벤트 | ||
|
|
||
| - [x] 영화를 불러오는 도중에는 스켈레톤 UI를 보여준다. | ||
| - [x] 포스터 클릭 시 백그라운드 영역에 해당 영화 포스터를 보여준다. | ||
| - [x] 클릭시 모달 창 띄우기 | ||
| - [x] 우측 상단 x버튼 혹은 모달 밖 화면 클릭 시 모달 창 끄기 | ||
|
|
||
| ### 더 보기 기능 | ||
| ### UI | ||
|
|
||
| - [x] '더보기' 버튼을 누르면 영화 20개를 추가로 띄운다. (띄운 후 아래 '더보기' 버튼 또 생김) | ||
| - [x] 포스터 클릭시 상세정보 모달 띄우기 | ||
| - [x] 포스터 사진 (poster_path) | ||
| - [x] 제목 (title) | ||
| - [x] 평균 별점 (vote_average) | ||
| - [x] 내 별점 | ||
| - [x] 줄거리 (overview) | ||
|
|
||
| ### 검색 기능 | ||
| ### 내 별점 | ||
|
|
||
| - [x] 검색란에 영화 제목을 입력해서 검색 버튼, Enter키를 눌러 필터링된 영화 20개를 띄운다. | ||
| - [x] 검색 결과가 존재하지 않으면 "검색 결과가 없습니다" 텍스트를 띄운다. | ||
| - [x] 검색 결과 화면에서 검색란에 검색어가 존재하지 않은 상태에서 검색버튼을 누르면 원상복귀. | ||
| - local storage 사용 | ||
|
|
||
| ## 테스트 시나리오 | ||
| * [x] 사용자는 영화에 대해 별점을 줄 수 있으며 새로고침하더라도 사용자가 남긴 별점은 유지되어야 한다. | ||
| * [x] 별점은 5개로 구성되어 있으며 한 개당 2점이며 1점 단위는 고려하지 않는다. | ||
| * [x] 2점: 최악이예요 | ||
| * [x] 4점: 별로예요 | ||
| * [x] 6점: 보통이에요 | ||
| * [x] 8점: 재미있어요 | ||
| * [x] 10점: 명작이에요 | ||
|
|
||
| - [x] '더보기' 버튼을 눌러 페이지를 확장시키면 영화 개수가 20개씩 늘어난다. | ||
| - [x] 검색란에 검색어를 입력하고 검색 버튼, Enter키를 누르면 필터링된 영화 목록을 보여준다. | ||
| - [x] 검색란에 검색어를 입력해도 결과가 존재하지 않다면 "검색 결과가 없습니다" 텍스트를 띄운다. | ||
| - [x] 포스터 클릭시 백그라운드에 해당 포스터의 정보가 띄워진다. | ||
| ## 무한 스크롤 | ||
|
|
||
| - [x] 더보기 버튼 대신 무한스크롤 적용 | ||
|
|
||
| ## 반응형 웹 | ||
|
|
||
| - 분기별로 잘라서 3가지 타입으로 진행 | ||
|
|
||
| - [x] 데스크톱 | ||
| - [x] 태블릿 | ||
| - [x] 모바일 | ||
|
|
||
| ## E2E 테스트 | ||
|
|
||
| - [x] 포스터를 클릭하면 모달창이 뜬다. | ||
| - [x] 내 별점을 클릭하면 별점이 적용이 된다. | ||
| - [x] 스크롤을 끝까지 내리면 다음 영화 리스트가 나온다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| describe('search test', () => { | ||
| beforeEach(() => { | ||
| cy.intercept('GET', '**/movie/*', { fixture: 'infoModal.json' }) | ||
| cy.intercept('GET', '**/movie/popular**', { fixture: 'popularMovies.json' }) | ||
| cy.intercept('GET', '**/search/movie**', { fixture: 'searchMovies.json' }) | ||
| }) | ||
|
|
||
| it('인기순 영화 페이지에서 두 번째 포스터를 클릭하면 영화 상세정보 모달이 띄워진다.', () => { | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
yuncic marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| cy.get('.thumbnail-list li') | ||
| .eq(1) | ||
| .find('#title') | ||
| .invoke('text') | ||
| .then((listTitle) => { | ||
| cy.get('.thumbnail-list li').eq(1).click() | ||
| cy.get('#modalBackground').should('have.class', 'active') | ||
| cy.get('#modalTitle') | ||
| .invoke('text') | ||
| .should((modalTitle) => { | ||
| expect(modalTitle.trim()).to.equal(listTitle.trim()) | ||
| }) | ||
| }) | ||
| }) | ||
|
|
||
| it('검색 결과에서 포스터를 클릭하면 모달이 열린다.', () => { | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
| cy.get('.search-bar').type('스파이더맨') | ||
| cy.get('.search-btn').click() | ||
| cy.get('.thumbnail-list li').first().click() | ||
| cy.get('#modalBackground').should('have.class', 'active') | ||
| cy.get('#modalTitle').should('not.be.empty') | ||
| }) | ||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,71 @@ | ||
| describe('more btn test', () => { | ||
| describe('infinite scroll test', () => { | ||
yuncic marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| beforeEach(() => { | ||
| cy.intercept('GET', '**/movie/popular**', { fixture: 'popularMovies.json' }) | ||
| cy.intercept('GET', '**/search/movie**', { fixture: 'searchMovies.json' }) | ||
| }) | ||
| it('페이지 접속 후 더보기 버튼을 1번 누르면 영화 개수가 40개가 된다.', () => { | ||
| cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
|
|
||
| cy.get('.item').should('have.length', 20) | ||
| it('스크롤을 내리면 추가 영화 목록을 불러온다.', () => { | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
|
|
||
| cy.get('.display-more-btn').click() | ||
| cy.get('.thumbnail-list li').should('have.length', 20) | ||
|
|
||
| cy.get('.item').should('have.length', 40) | ||
| }) | ||
| it('페이지 접속 후 더보기 버튼을 10번 누르면 영화 개수가 220개가 된다.', () => { | ||
| cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
| cy.get('.item').should('have.length', 20) | ||
| for (let i = 0; i < 10; i++) { | ||
| cy.get('.display-more-btn').click() | ||
| } | ||
| cy.get('.item').should('have.length', 220) | ||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 40) | ||
yuncic marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 60) | ||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 80) | ||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 100) | ||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 120) | ||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 140) | ||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 160) | ||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 180) | ||
|
|
||
| cy.get('.thumbnail-list li').last().scrollIntoView() | ||
|
|
||
| cy.get('.thumbnail-list li').should('have.length', 200) | ||
| }) | ||
| }) | ||
|
|
||
| // describe('more btn test', () => { | ||
| // beforeEach(() => { | ||
| // cy.intercept('GET', '**/movie/popular**', { fixture: 'popularMovies.json' }) | ||
| // cy.intercept('GET', '**/search/movie**', { fixture: 'searchMovies.json' }) | ||
| // }) | ||
| // it('페이지 접속 후 더보기 버튼을 1번 누르면 영화 개수가 40개가 된다.', () => { | ||
| // cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
|
|
||
| // cy.get('.item').should('have.length', 20) | ||
|
|
||
| // cy.get('.display-more-btn').click() | ||
|
|
||
| // cy.get('.item').should('have.length', 40) | ||
| // }) | ||
| // it('페이지 접속 후 더보기 버튼을 10번 누르면 영화 개수가 220개가 된다.', () => { | ||
| // cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
| // cy.get('.item').should('have.length', 20) | ||
| // for (let i = 0; i < 10; i++) { | ||
| // cy.get('.display-more-btn').click() | ||
| // } | ||
| // cy.get('.item').should('have.length', 220) | ||
| // }) | ||
| // }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ describe('search test', () => { | |
| cy.intercept('GET', '**/search/movie**', { fixture: 'searchMovies.json' }) | ||
| }) | ||
| it('검색어를 입력한 뒤 검색 버튼을 누르면 필터링된 영화 목록을 보여준다.', () => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 우선 테스트 시나리오를 유저 행동 기반으로 작성한 점은 정말 좋다고 생각해요.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 검색을 하지 않았을때 뽑은 타이틀 텍스트와 비교하기 위해 그랬던 것인데, fixture 데이터를 정의했을 시점에 수정했어야하는데 놓친 것 같습니다..! |
||
| cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
|
|
||
| cy.get('.thumbnail-list li') | ||
| .first() | ||
|
|
@@ -25,7 +25,7 @@ describe('search test', () => { | |
| }) | ||
|
|
||
| it('검색어를 입력한 뒤 엔터키를 누르면 필터링된 영화 목록을 보여준다.', () => { | ||
| cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
|
|
||
| cy.get('.thumbnail-list li') | ||
| .first() | ||
|
|
@@ -45,23 +45,23 @@ describe('search test', () => { | |
| }) | ||
| it("검색란에 검색어를 입력해도 결과가 존재하지 않다면 '검색 결과가 없습니다' 텍스트를 띄운다", () => { | ||
| cy.intercept('GET', '**/search/movie**', { body: { results: [] } }) | ||
| cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
| cy.get('.search-bar').type('ㄴㅇ러ㅏㅗㅁ라ㅗ어ㅏ로머ㅏJklhdskldh') | ||
| cy.get('.search-btn').click() | ||
| cy.get('.search-error-text').should('have.text', '검색 결과가 없습니다.') | ||
| }) | ||
|
|
||
| it('네트워크 오류 시 알림을 띄운다', () => { | ||
| cy.intercept('GET', '**/movie/popular**', { forceNetworkError: true }) | ||
| cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
| cy.on('window:alert', (text) => { | ||
| expect(text).to.equal('네트워크 오류가 발생하였습니다.') | ||
| }) | ||
| }) | ||
|
|
||
| it('API 오류 시 알림을 띄운다', () => { | ||
| cy.intercept('GET', '**/movie/popular**', { statusCode: 401 }) | ||
| cy.visit('https://javascript-movie-review-dvlk.vercel.app/') | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
| cy.on('window:alert', (text) => { | ||
| expect(text).to.equal('데이터를 불러오지 못했습니다.') | ||
| }) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| describe('별점 매기기 테스트', () => { | ||
| beforeEach(() => { | ||
| cy.intercept('GET', '**/movie/*', { fixture: 'infoModal.json' }) | ||
| cy.intercept('GET', '**/movie/popular**', { fixture: 'popularMovies.json' }) | ||
| cy.clearLocalStorage() | ||
| cy.visit('https://javascript-movie-review-dvlk-a6xn5spuo-yun-cics-projects.vercel.app/') | ||
| cy.get('.thumbnail-list li').first().click() | ||
| cy.get('#modalBackground').should('have.class', 'active') | ||
| }) | ||
|
|
||
| it('별점 클릭 시 해당 별점 텍스트가 표시된다.', () => { | ||
| cy.get('.star-icon[data-value="2"]').click() | ||
| cy.get('.my-rate-text').should('have.text', '최악이에요 (2/10)') | ||
|
|
||
| cy.get('.star-icon[data-value="4"]').click() | ||
| cy.get('.my-rate-text').should('have.text', '별로예요 (4/10)') | ||
|
|
||
| cy.get('.star-icon[data-value="6"]').click() | ||
| cy.get('.my-rate-text').should('have.text', '보통이에요 (6/10)') | ||
|
|
||
| cy.get('.star-icon[data-value="8"]').click() | ||
| cy.get('.my-rate-text').should('have.text', '재미있어요 (8/10)') | ||
|
|
||
| cy.get('.star-icon[data-value="10"]').click() | ||
| cy.get('.my-rate-text').should('have.text', '명작이에요 (10/10)') | ||
| }) | ||
|
|
||
| it('별점 클릭 시 클릭한 별까지 채워진 별로 변경된다.', () => { | ||
| // 클릭 전 빈 별 src 저장 | ||
| cy.get('.star-icon[data-value="10"]') | ||
| .invoke('attr', 'src') | ||
| .then((emptySrc) => { | ||
| cy.get('.star-icon[data-value="6"]').click() | ||
|
|
||
| // 클릭한 별까지는 src가 빈 별과 달라야 함 | ||
| cy.get('.star-icon[data-value="2"]').invoke('attr', 'src').should('not.equal', emptySrc) | ||
| cy.get('.star-icon[data-value="4"]').invoke('attr', 'src').should('not.equal', emptySrc) | ||
| cy.get('.star-icon[data-value="6"]').invoke('attr', 'src').should('not.equal', emptySrc) | ||
|
|
||
| // 클릭하지 않은 별은 여전히 빈 별이어야 함 | ||
| cy.get('.star-icon[data-value="8"]').invoke('attr', 'src').should('equal', emptySrc) | ||
| cy.get('.star-icon[data-value="10"]').invoke('attr', 'src').should('equal', emptySrc) | ||
| }) | ||
| }) | ||
|
|
||
| it('별점 클릭 시 localStorage에 별점이 저장된다.', () => { | ||
|
||
| cy.get('.star-icon[data-value="8"]').click() | ||
|
|
||
| // infoModal.json movie id 83533 | ||
| cy.window().then((win) => { | ||
| expect(win.localStorage.getItem('rating_83533')).to.equal('8') | ||
| }) | ||
| }) | ||
|
|
||
| it('모달을 닫았다가 다시 열면 이전에 저장한 별점이 복원된다.', () => { | ||
| cy.get('.star-icon[data-value="6"]').click() | ||
| cy.get('.my-rate-text').should('have.text', '보통이에요 (6/10)') | ||
|
|
||
| cy.get('#closeModal').click() | ||
| cy.get('#modalBackground').should('not.have.class', 'active') | ||
|
|
||
| cy.get('.thumbnail-list li').first().click() | ||
| cy.get('#modalBackground').should('have.class', 'active') | ||
|
|
||
| cy.get('.my-rate-text').should('have.text', '보통이에요 (6/10)') | ||
| cy.get('.star-icon[data-value="8"]') | ||
| .invoke('attr', 'src') | ||
| .then((emptySrc) => { | ||
| cy.get('.star-icon[data-value="2"]').invoke('attr', 'src').should('not.equal', emptySrc) | ||
| cy.get('.star-icon[data-value="6"]').invoke('attr', 'src').should('not.equal', emptySrc) | ||
| cy.get('.star-icon[data-value="8"]').invoke('attr', 'src').should('equal', emptySrc) | ||
| }) | ||
| }) | ||
| }) | ||
Uh oh!
There was an error while loading. Please reload this page.