diff --git a/.github/pull_request_template2.md b/.github/pull_request_template2.md new file mode 100644 index 0000000000..9210f13e66 --- /dev/null +++ b/.github/pull_request_template2.md @@ -0,0 +1,33 @@ +## ๐ฏ ๋ฏธ์ ์๊ฐ + +- API ์ฐ๋์ ํตํ ๋น๋๊ธฐ ํต์ ํ์ต +- ์ฌ์ฉ์ ์๋๋ฆฌ์ค ๊ธฐ๋ฐ E2E ํ ์คํธ + +--- + +## ๐ต๏ธ ์ ํ ๋ฆฌ๋ทฐ(Self-Review) + +### ์ ์ถ ์ ์ฒดํฌ ๋ฆฌ์คํธ + +- [x] ๊ธฐ๋ฅ ์๊ตฌ ์ฌํญ์ ๋ชจ๋ ๊ตฌํํ๊ณ , ์ ์์ ์ผ๋ก ๋์ํ๋์ง ํ์ธํ๋์? +- [x] ๊ธฐ๋ณธ์ ์ธ ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ ์ฌํญ(์ฝ๋ ์ปจ๋ฒค์ , ์๋ฌ ํธ๋ค๋ง ๋ฑ)์ ์ค์ํ๋์? +- [ ] ํ ์คํธ ์ฝ๋๋ ๋ชจ๋ ์ ์์ ์ผ๋ก ์คํ๋๋์? (ํ์ ์, API Mocking ๋ฑ) +- [ ] (ํด๋นํ๋ ๊ฒฝ์ฐ) ๋ฐฐํฌํ ๋ฐ๋ชจ ํ์ด์ง์ ์ ์์ ์ผ๋ก ์ ๊ทผํ ์ ์๋์? + - (ํด๋นํ๋ ๊ฒฝ์ฐ) ๋ฐฐํฌ ๋งํฌ ๊ธฐ์ : \***\*\_\_\*\*** + +### ๋ฆฌ๋ทฐ ์์ฒญ & ๋ ผ์ํ๊ณ ์ถ์ ๋ด์ฉ + +#### 1) ์ด๋ฒ ๋จ๊ณ์์ ๊ฐ์ฅ ๋ง์ด ๊ณ ๋ฏผํ๋ ๋ฌธ์ ์ ํด๊ฒฐ ๊ณผ์ ์์ ๋ฐฐ์ด ์ + +#### 2) ์ด๋ฒ ๋ฆฌ๋ทฐ๋ฅผ ํตํด ๋ ผ์ํ๊ณ ์ถ์ ๋ถ๋ถ + +--- + +## โ ๋ฆฌ๋ทฐ์ด ์ฒดํฌ ํฌ์ธํธ + + + +- [ ] ๋น๋๊ธฐ ํต์ ๊ณผ์ ์์ ๋ฐ์ํ ์ ์๋ ์์ธ(๋คํธ์ํฌ, ์๋ฒ ์ค๋ฅ ๋ฑ)๋ฅผ ๊ณ ๋ คํ๋๊ฐ? +- [ ] ๋น๋๊ธฐ ๋ก์ง์์ ์ฝ๋ฐฑ ์ง์ฅ ์์ด, ์ ์ ํ async/await ๋๋ Promise๋ฅผ ํ์ฉํ๋๊ฐ? +- [ ] ์ญํ ๊ณผ ์ฑ ์์ ๋ฐ๋ผ ํ์ผ/๋ชจ๋์ ๋ถ๋ฆฌํ๋๊ฐ? (UI, ๋น์ฆ๋์ค ๋ก์ง, API ํธ์ถ ๋ฑ) diff --git a/README2.md b/README2.md new file mode 100644 index 0000000000..a322e0b077 --- /dev/null +++ b/README2.md @@ -0,0 +1,43 @@ +# javascript-movie-review + +FE ๋ ๋ฒจ1 ์ํ ๋ฆฌ๋ทฐ ๋ฏธ์ 2๋จ๊ณ + +## ๊ธฐ๋ฅ ์๊ตฌ ์ฌํญ +### ๋๋ณด๊ธฐ ๋ฒํผ ๋ฌดํ์คํฌ๋กค๋ก ๋ณ๊ฒฝ +- [x] ๊ธฐ์กด ๋๋ณด๊ธฐ ๋ฒํผ ํด๋ฆญ ์ ์ํ๋ชฉ๋ก์ ํธ์ถํ๋ ์กฐ๊ฑด์ ํ๋ฉด ๋งจ ์๋๋ก ๋ด๋ ค์์ ๋๋ก ๋ณ๊ฒฝ + +### ์ํ ์์ธ์ ๋ณด ์กฐํ +- [x] ์์ธํ ๋ณด๊ธฐ ํด๋ฆญ ์ ์ถ๋ ฅ +- [x] ์ํ ์ฌ๋ค์ผ ํด๋ฆญ ์ ์ถ๋ ฅ +- [x] ์์ธ ์ ๋ณด ๋ก๋ฉ ์ค ์ค์ผ๋ ํค ์ฒ๋ฆฌ +- [x] ๋ชจ๋ฌ ์ฐฝ ๋ซ๊ธฐ ๊ธฐ๋ฅ + - [x] X ํค + - [x] esc ํค + - [x] ๋ชจ๋ฌ ์ฐฝ ๋ฐ๊นฅ ํด๋ฆญ +- ์ถ๋ ฅํ ๋ด์ฉ + - [x] ์ํ ํฌ์คํฐ + - [x] ์ํ ์ ๋ชฉ + - [x] ์ฐ๋ + - [x] ์ฅ๋ฅด + - [x] ํ๊ท ๋ณ์ + - [x] ๋ด ๋ณ์ (๋ณ์ ๊ทธ๋ฆผ + ๋ณ์ ์ ๋ฐ๋ฅธ ์ค๋ช + (8/10)๊ณผ ๊ฐ์ ๋ณ์ ์์นํ) + - [x] ์ค๊ฑฐ๋ฆฌ +- [x] API ์๋ฌ ์ฒ๋ฆฌ + +### UI/UX ๊ฐ์ +- [x] ๋ฐ์ํ ์น์ ๊ตฌ์ํ์ฌ ๋๋ฐ์ด์ค์ ๋๋น์ ๋ฐ๋ผ ๋ ์ด์์์ด ์กฐ์ ๋๋๋ก ๋ณ๊ฒฝ + - [x] ๋๋น์ ๋ฐ๋ผ ์ํ ์ถ๋ ฅ ๊ฐฏ์ ๋ฐ์ํ์ผ๋ก ๋ณ๊ฒฝ + - [x] ๋ชจ๋ฌ ์ฐฝ ๋ฐ์คํฌํฐ์ ์ค์ ์ถ๋ ฅ, ํ๋ธ๋ฆฟ์ด๋ ๋ชจ๋ฐ์ผ์ ํ๋จ ์ถ๋ ฅ์ผ๋ก ์ ์ + - [x] ์์ธํ ๋ณด๊ธฐ ์ฐฝ์์ ํ๋ฉด์ด ๋๋ฌด ์์ผ๋ฉด ํฌ์คํฐ ์ถ๋ ฅ x + +### ๋ณ์ ๋งค๊ธฐ๊ธฐ ๊ธฐ๋ฅ +- [x] 2์ ๋จ์์ ๋ณ์ ๋งค๊ธฐ๊ธฐ ๊ธฐ๋ฅ + - [x] ์๋ก๊ณ ์นจํด๋ ๋ณ์ ์ ์ง + - [x] ๋ณ์ UI ํธ๋ฒ, ํด๋ฆญ ์ด๋ฒคํธ ์ฒ๋ฆฌ + - [x] ์๋ก ์ ๋ ฅ๋ฐ์ ๋ณ์ ๋ฐ์ดํฐ๋ฅผ ์์ธํ๋ฉด์ ๋ฐ์ +- [x] ๋ก์ปฌ ์คํ ๋ฆฌ์ง ๋ฐ ์๋ฒAPI๋ก ์ฝ๊ณ ์์ ํ๊ฒ ๊ฐ์๋ผ์ธ ์ ์๋ ๊ตฌ์กฐ๋ก ์ ์ + +### E2E ํ ์คํธ +- [x] ๋ฌดํ ์คํฌ๋กค ๋์ ํ ์คํธ +- [x] ์์ธ ์ ๋ณด ๋ชจ๋ฌ ์ฌ๋ซ๊ธฐ ํ ์คํธ +- [x] ๋ณ์ ํ๊ฐ, ๋ฐ์, ์๋ก๊ณ ์นจ ์ ๋ฐ์ดํฐ ์ ์ง ํ ์คํธ \ No newline at end of file diff --git a/cypress/e2e/movie.cy.ts b/cypress/e2e/movie.cy.ts new file mode 100644 index 0000000000..bd337aefb3 --- /dev/null +++ b/cypress/e2e/movie.cy.ts @@ -0,0 +1,117 @@ +describe('์ํ ๋ฆฌ๋ทฐ step2 ํ ์คํธ', () => { + beforeEach(() => { + // ์ธ๊ธฐ ์ํ ๋ชฉ๋ก API ๊ฐ๋ก์ฑ๊ธฐ + cy.intercept('GET', '**/movie/popular*', { + fixture: 'popularMovies.json', + }).as('getPopularMovies'); + + // ์ํ ์์ธ ์ ๋ณด API๋ฅผ ๊ฐ๋ก์ฑ๊ธฐ + cy.intercept('GET', /\/movie\/\d+/, { + fixture: 'movieDetail.json', + }).as('getMovieDetail'); + + cy.visit('/'); + + cy.wait('@getPopularMovies'); + }); + + describe('๋ฌดํ ์คํฌ๋กค ๋์ ํ ์คํธ', () => { + it('ํ๋ฉด์ ๋๊น์ง ์คํฌ๋กคํ๋ฉด ์๋ก์ด ์ํ ๋ชฉ๋ก์ด ์ถ๊ฐ๋ก ๋ก๋๋๋ค.', () => { + // ๋ ๋๋ง๋ ์ํ ์์ดํ ๊ฐ์ ์ ์ฅ + cy.get('.thumbnail-list .movie-item').then(($items) => { + const initialCount = $items.length; + + // ๋ฐ๋ฅ์ผ๋ก ์คํฌ๋กคํ์ฌ ๋ ๋ณด๊ธฐ ํธ๋ฆฌ๊ฑฐ + cy.scrollTo('bottom'); + + // ๋ ๋๋ง ๋๊ธฐ + cy.wait('@getPopularMovies'); + + // ์ํ ์์ดํ ๊ฐ์๊ฐ ๋์ด๋ฌ๋์ง ๊ฒ์ฆ + cy.get('.thumbnail-list .movie-item') + .should('have.length.greaterThan', initialCount); + }); + }); + }); + + describe('์์ธ ์ ๋ณด ๋ชจ๋ฌ ์ฌ๋ซ๊ธฐ ํ ์คํธ', () => { + // ํด๋ฆญ ํ์ธ + it('์ํ ํด๋ฆญ ์ ๋ชจ๋ฌ์ด ์ด๋ฆฌ๊ณ , ๋ซ๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ชจ๋ฌ์ด ๋ซํ๋ค.', () => { + // ์ฒซ ๋ฒ์งธ ์ํ ์์ดํ ํด๋ฆญ + cy.get('.thumbnail-list .movie-item').first().click(); + + // ๋ชจ๋ฌ ๋ฐ์ดํฐ ์๋ต ๋๊ธฐ + cy.wait('@getMovieDetail'); + + // ๋ชจ๋ฌ์ด ํ์ฑํ๋์๋์ง ํ์ธ (active ํด๋์ค ๋ฐ ํ๋ฉด๋ ธ์ถ) + cy.get('#modalBackground').should('have.class', 'active'); + cy.get('#modalContainer').should('be.visible'); + + // ๋ซ๊ธฐ ๋ฒํผ ํด๋ฆญ + cy.get('#closeModal').click(); + + // ๋ชจ๋ฌ์ด ์ ์์ ์ผ๋ก ๋ซํ๋์ง ํ์ธ + cy.get('#modalBackground').should('not.have.class', 'active'); + }); + + // ๋ฐฐ๊ฒฝํด๋ฆญ ํ์ธ + it('๋ชจ๋ฌ ๋ฐฐ๊ฒฝ์ ํด๋ฆญํด๋ ๋ชจ๋ฌ์ด ๋ซํ๋ค.', () => { + cy.get('.thumbnail-list .movie-item').first().click(); + + // ๋ฐฐ๊ฒฝ ์์ญ ํด๋ฆญ + cy.get('#modalBackground').click('topLeft', { force: true }); + + cy.get('#modalBackground').should('not.have.class', 'active'); + }); + + // ESCํค ํ์ธ + it('ESC ํค๋ฅผ ๋๋ฅด๋ฉด ๋ชจ๋ฌ์ด ๋ซํ๋ค.', () => { + cy.get('.thumbnail-list .movie-item').first().click(); + cy.get('#modalBackground').should('have.class', 'active'); + + // body ํ๊ทธ์ ๋๊ณ ESC ํค ์ ๋ ฅ ์ด๋ฒคํธ ๋ฐ์ + cy.get('body').type('{esc}'); + + // ๋ชจ๋ฌ์ด ์ ์์ ์ผ๋ก ๋ซํ๋์ง ํ์ธ + cy.get('#modalBackground').should('not.have.class', 'active'); + }); + }); + + describe('๋ณ์ ํ๊ฐ ๋ฐ ๋ฐ์ดํฐ ์ ์ง ํ ์คํธ', () => { + it('๋ณ์ ์ ์ ํํ๋ฉด ๋ฐ์๋๊ณ , ์๋ก๊ณ ์นจ ํ์๋ ํด๋น ์ ์๊ฐ ์ ์ง๋๋ค.', () => { + const TARGET_SCORE = 8; + const RATING_TEXT = '์ฌ๋ฏธ์์ด์'; + + // ๋ชจ๋ฌ ์ด๊ธฐ + cy.get('.thumbnail-list .movie-item').first().click(); + + // 8์ ํด๋ฆญ + cy.get(`.rate-star-img[data-score="${TARGET_SCORE}"]`).click(); + + // UI์ ํ๊ฐ ๋ฌธ๊ตฌ์ ์ ์๊ฐ ๋ฐ์๋์๋์ง ํ์ธ + cy.get('#ratingDescription') + .should('contain.text', RATING_TEXT) + .and('contain.text', `(${TARGET_SCORE}/10)`); + + // ๋ชจ๋ฌ ๋ซ๊ธฐ + cy.get('#closeModal').click(); + + // ํ์ด์ง ์๋ก๊ณ ์นจ + cy.reload(); + cy.wait('@getPopularMovies'); + + // ๋์ผํ ์ํ์ ๋ชจ๋ฌ์ ๋ค์ ์ด๊ธฐ + cy.get('.thumbnail-list .movie-item').first().click(); + + // LocalStorage์์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ฐ์ ธ์์ ์ด์ ์ ์๊ฐ ๊ทธ๋๋ก ํ์๋๋์ง ํ์ธ + cy.get('#ratingDescription') + .should('contain.text', RATING_TEXT) + .and('contain.text', `(${TARGET_SCORE}/10)`); + + // ๋ณ ์ด๋ฏธ์ง ์์ค๋ ์ฑ์์ง ๋ณ(star_filled)์ธ์ง ํ์ธ (์ฒซ ๋ฒ์งธ ๋ณ์ ์์) + cy.get(`.rate-star-img[data-score="2"]`) + .should('have.attr', 'src') + .and('include', 'star_filled'); + }); + }); +}); \ No newline at end of file diff --git a/cypress/e2e/spec.cy.ts b/cypress/e2e/spec.cy.ts index 34fbd142fa..f07a861675 100644 --- a/cypress/e2e/spec.cy.ts +++ b/cypress/e2e/spec.cy.ts @@ -41,16 +41,16 @@ describe('์ํ ๋ฆฌ๋ทฐ ์ฑ E2E ํ ์คํธ', () => { cy.get('.thumbnail-list > li').should('have.length', 20); }); - it('๋๋ณด๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ค์ ํ์ด์ง์ ์ํ 20๊ฐ๋ฅผ ์ถ๊ฐ๋ก ๋ ๋๋งํ๋ค.', () => { - cy.visit('/'); - cy.wait('@getPopularMovies'); + // it('๋๋ณด๊ธฐ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ค์ ํ์ด์ง์ ์ํ 20๊ฐ๋ฅผ ์ถ๊ฐ๋ก ๋ ๋๋งํ๋ค.', () => { + // cy.visit('/'); + // cy.wait('@getPopularMovies'); - cy.get('#more-page-button').click(); - cy.wait('@getNextPopularMovies'); + // cy.get('#more-page-button').click(); + // cy.wait('@getNextPopularMovies'); - // ๊ธฐ์กด 20๊ฐ + ์ถ๊ฐ 20๊ฐ = 40๊ฐ - cy.get('.thumbnail-list > li').should('have.length', 40); - }); + // // ๊ธฐ์กด 20๊ฐ + ์ถ๊ฐ 20๊ฐ = 40๊ฐ + // cy.get('.thumbnail-list > li').should('have.length', 40); + // }); }); context('2. ๊ฒ์ ๊ธฐ๋ฅ', () => { diff --git a/cypress/fixtures/movieDetail.json b/cypress/fixtures/movieDetail.json new file mode 100644 index 0000000000..70a933f838 --- /dev/null +++ b/cypress/fixtures/movieDetail.json @@ -0,0 +1,26 @@ +{ + "id": 1022789, + "title": "์ธ์ฌ์ด๋ ์์ 2", + "poster_path": "/vpnVM9B6NMmQpWeZvzRxHXlNpzT.jpg", + "release_date": "2024-06-12", + "genres": [ + { + "id": 16, + "name": "์ ๋๋ฉ์ด์ " + }, + { + "id": 10751, + "name": "๊ฐ์กฑ" + }, + { + "id": 12, + "name": "๋ชจํ" + }, + { + "id": 35, + "name": "์ฝ๋ฏธ๋" + } + ], + "vote_average": 8.5, + "overview": "13์ด์ด ๋ ๋ผ์ผ๋ฆฌ์ ๋จธ๋ฆฟ์ ๊ฐ์ ์ปจํธ๋กค ๋ณธ๋ถ์ ๋ถ์, ๋นํฉ, ๋ฐ๋ถ, ๋ถ๋ฝ์ ๋ฏ์ ๊ฐ์ ๋ค์ด ์๋กญ๊ฒ ๋ฑ์ฅํ๋ฉด์ ํํ๋กญ๋ ์ผ์์ด ๊นจ์ง๊ณ ๋ค์ ์์๋ ์๊ธฐ์ ๋ชจํ์ ๋ค๋ฃฌ ์ ๋๋ฉ์ด์ ์ํ" +} diff --git a/cypress/fixtures/popularMovies.json b/cypress/fixtures/popularMovies.json new file mode 100644 index 0000000000..1c0a9c9dbf --- /dev/null +++ b/cypress/fixtures/popularMovies.json @@ -0,0 +1,41 @@ +{ + "page": 1, + "results": [ + { + "id": 1022789, + "title": "์ธ์ฌ์ด๋ ์์ 2", + "poster_path": "/vpnVM9B6NMmQpWeZvzRxHXlNpzT.jpg", + "backdrop_path": "/stKGOm8UyhuLPR9sLsGAXo0I94w.jpg", + "vote_average": 8.5 + }, + { + "id": 533535, + "title": "๋ฐ๋ํ๊ณผ ์ธ๋ฒ๋ฆฐ", + "poster_path": "/8cdWjvZQUExUUTzyp4t6EDMubfO.jpg", + "backdrop_path": "/yDHYTfA3R0jFYba16ZBRWUP1lNl.jpg", + "vote_average": 7.9 + }, + { + "id": 1029528, + "title": "์ํผ๋ฐฐ๋ 4", + "poster_path": "/3w84hCFJATpiCO5g8hpdWVPBcbF.jpg", + "backdrop_path": "/lgkPzcOSnTvjeMnuFzozRO5HHw1.jpg", + "vote_average": 7.4 + }, + { + "id": 653346, + "title": "ํน์ฑํ์ถ: ์๋ก์ด ์๋", + "poster_path": "/fQZ5o2eY9KusVq6qO2o1EudV9Iq.jpg", + "backdrop_path": "/fqv8v6AycXKsivp1T5yKtLbGXce.jpg", + "vote_average": 6.9 + }, + { + "id": 748783, + "title": "๊ฐํ๋ ๋ ๋ฌด๋น", + "poster_path": "/a0A9YlRhaV7Z1rA0N6P4qF8w3rO.jpg", + "backdrop_path": "/xg27NrZaAKk4pM1r7K531Qk7u0D.jpg", + "vote_average": 7.1 + } + ], + "total_pages": 100 +} diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000000..d8476f93ed Binary files /dev/null and b/images/logo.png differ diff --git a/images/modal_button_close.png b/images/modal_button_close.png new file mode 100644 index 0000000000..b352a220dc Binary files /dev/null and b/images/modal_button_close.png differ diff --git a/images/star_empty.png b/images/star_empty.png new file mode 100644 index 0000000000..bf32725179 Binary files /dev/null and b/images/star_empty.png differ diff --git a/images/star_filled.png b/images/star_filled.png new file mode 100644 index 0000000000..5b6f299937 Binary files /dev/null and b/images/star_filled.png differ diff --git a/images/woowacourse_logo.png b/images/woowacourse_logo.png new file mode 100644 index 0000000000..e64c002e12 Binary files /dev/null and b/images/woowacourse_logo.png differ diff --git a/index.html b/index.html index 4186769bc3..1c86c6e1d5 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,7 @@ +
@@ -16,13 +17,26 @@