-
Notifications
You must be signed in to change notification settings - Fork 155
[2단계 - 상세 정보 & UI/UX 개선하기] 벤지 미션 제출합니다. #297
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: hjkim0905
Are you sure you want to change the base?
Changes from 39 commits
724ba60
2a77102
84c4ce3
2bef250
287c9cf
d7def81
462c588
95f87b7
34af311
6b8f71d
f1e0003
288df06
09a995a
263a7d9
31475e8
5007a55
7677998
e65f090
46facd9
6175c37
41498bc
3e83ddd
eb067d9
c206614
a6dc551
aca4d5b
9a9adc9
bfba58b
a4396a7
8688175
ef1c0c4
9ce1f8e
5ef2a23
793efd9
6591cc1
90ab548
efc47a5
281b2f2
b8bfe2b
d04306f
a7d53aa
c9d585e
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 |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| describe("모달 열기 테스트", () => { | ||
| beforeEach(() => { | ||
| cy.intercept("GET", "**/movie/popular**", { fixture: "movies.json" }).as( | ||
| "getMovies", | ||
| ); | ||
| cy.intercept("GET", "**/movie/1001**", { fixture: "moviedetail.json" }).as( | ||
| "getMovieDetail", | ||
| ); | ||
| cy.visit("http://localhost:5173"); | ||
| cy.wait("@getMovies"); | ||
| }); | ||
|
|
||
| it("영화 아이템을 클릭하면 모달이 열린다", () => { | ||
| cy.get(".thumbnail-list li").first().find(".item").click(); | ||
| cy.wait("@getMovieDetail"); | ||
| cy.get("#modalBackground").should("have.class", "active"); | ||
| cy.get(".modal-container h2").should("contain", "영화 1"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("모달 닫기 테스트", () => { | ||
| beforeEach(() => { | ||
| cy.intercept("GET", "**/movie/popular**", { fixture: "movies.json" }).as( | ||
| "getMovies", | ||
| ); | ||
| cy.intercept("GET", "**/movie/1001**", { fixture: "moviedetail.json" }).as( | ||
| "getMovieDetail", | ||
| ); | ||
| cy.visit("http://localhost:5173"); | ||
| cy.wait("@getMovies"); | ||
| cy.get(".thumbnail-list li").first().find(".item").click(); | ||
| cy.wait("@getMovieDetail"); | ||
| }); | ||
|
|
||
| it("닫기 버튼 클릭 시 모달이 닫힌다", () => { | ||
| cy.get("#closeModal").click(); | ||
| cy.get("#modalBackground").should("not.have.class", "active"); | ||
| cy.get(".modal-container").should("not.exist"); | ||
| }); | ||
|
|
||
| it("Escape 키 입력 시 모달이 닫힌다", () => { | ||
| cy.get("body").type("{esc}"); | ||
| cy.get("#modalBackground").should("not.have.class", "active"); | ||
| cy.get(".modal-container").should("not.exist"); | ||
| }); | ||
|
|
||
| it("배경 클릭 시 모달이 닫힌다", () => { | ||
| cy.get("#modalBackground").click({ force: true }); | ||
| cy.get("#modalBackground").should("not.have.class", "active"); | ||
| cy.get(".modal-container").should("not.exist"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("모달 반응형 테스트 - 태블릿", () => { | ||
| beforeEach(() => { | ||
| cy.viewport(768, 1024); | ||
| cy.intercept("GET", "**/movie/popular**", { fixture: "movies.json" }).as( | ||
| "getMovies", | ||
| ); | ||
| cy.intercept("GET", "**/movie/1001**", { fixture: "moviedetail.json" }).as( | ||
| "getMovieDetail", | ||
| ); | ||
| cy.visit("http://localhost:5173"); | ||
| cy.wait("@getMovies"); | ||
| cy.get(".thumbnail-list li").first().find(".item").click(); | ||
| cy.wait("@getMovieDetail"); | ||
| }); | ||
|
|
||
| it("태블릿 화면에서 모달이 하단 고정으로 표시된다", () => { | ||
| cy.get("#modalBackground").should("have.css", "align-items", "flex-end"); | ||
| cy.get(".modal").should("have.css", "width", "768px"); | ||
| }); | ||
|
|
||
| it("태블릿 화면에서 포스터와 설명이 세로 정렬된다", () => { | ||
| cy.get(".modal-container").should("have.css", "flex-direction", "column"); | ||
| cy.get(".modal-image img").should("have.css", "width", "160px"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("모달 반응형 테스트 - 모바일", () => { | ||
| beforeEach(() => { | ||
| cy.viewport(375, 667); | ||
| cy.intercept("GET", "**/movie/popular**", { fixture: "movies.json" }).as( | ||
| "getMovies", | ||
| ); | ||
| cy.intercept("GET", "**/movie/1001**", { fixture: "moviedetail.json" }).as( | ||
| "getMovieDetail", | ||
| ); | ||
| cy.visit("http://localhost:5173"); | ||
| cy.wait("@getMovies"); | ||
| cy.get(".thumbnail-list li").first().find(".item").click(); | ||
| cy.wait("@getMovieDetail"); | ||
| }); | ||
|
|
||
| it("모바일 화면에서 포스터 이미지가 숨겨진다", () => { | ||
| cy.get(".modal-image").should("have.css", "display", "none"); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,40 +1,44 @@ | ||
| describe("인기영화 렌더링 테스트", () => { | ||
| beforeEach(() => { | ||
| cy.visit("localhost:5173"); | ||
| }); | ||
|
|
||
| it("웹에 접근을 하면 인기 영화 20개를 랜더링 한다", () => { | ||
| // page=2 자동 로드를 막아 20개만 렌더링되도록 intercept | ||
| cy.intercept( | ||
| "GET", | ||
| "https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=2", | ||
| { body: { results: [], total_pages: 1 } }, | ||
| ); | ||
| cy.visit("localhost:5173"); | ||
| cy.get(".thumbnail-list li").should("have.length", 20); | ||
| }); | ||
|
|
||
| it("인기 영화 화면에서 더보기 버튼을 누르면 인기 영화 20개를 추가로 렌더링 한다", () => { | ||
| cy.get("#load-movie-button").click(); | ||
| it("인기 영화 화면에서 화면의 끝에 도달하면 인기 영화 20개를 추가로 렌더링 한다", () => { | ||
| cy.visit("localhost:5173"); | ||
| cy.get("#scroll-sentinel").scrollIntoView(); | ||
| cy.get(".thumbnail-list li").should("have.length", 40); | ||
| }); | ||
| }); | ||
|
|
||
| describe("인기 영화 더보기 버튼이 숨겨지는지 테스트", () => { | ||
| describe("인기 영화 무한스크롤 테스트", () => { | ||
| beforeEach(() => { | ||
| cy.intercept( | ||
| "GET", | ||
| "https://api.themoviedb.org/3/movie/popular?language=en-US&page=1", | ||
| "https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=1", | ||
| { fixture: "movies.json" }, | ||
| ).as("getMovies"); | ||
|
|
||
| cy.intercept( | ||
| "GET", | ||
| "https://api.themoviedb.org/3/movie/popular?language=en-US&page=2", | ||
| "https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=2", | ||
| { fixture: "movies2.json" }, | ||
| ).as("getMoviesPage2"); | ||
|
|
||
| cy.visit("http://localhost:5173"); | ||
| }); | ||
|
|
||
| it("마지막 페이지 도달 시 더보기 버튼이 사라진다", () => { | ||
| it("마지막 페이지 도달 시 스크롤 시에 영화를 더 불러오지 않는다.", () => { | ||
| cy.wait("@getMovies"); | ||
| cy.get("#load-movie-button").click(); | ||
| cy.get("#scroll-sentinel").scrollIntoView(); | ||
| cy.wait("@getMoviesPage2"); | ||
| cy.get("#load-movie-button").should("have.css", "display", "none"); | ||
| cy.get(".thumbnail-list li").should("have.length", 40); | ||
| }); | ||
| }); | ||
|
|
||
|
|
@@ -57,8 +61,14 @@ describe("검색영화 렌더링 테스트", () => { | |
| }); | ||
|
Comment on lines
+50
to
+61
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. 검색 시나리오가 실 API에 의존해 테스트가 흔들릴 수 있습니다 Line 50-61은 intercept 없이 외부 응답에 의존합니다. CI 안정성을 위해 검색 결과 유/무 시나리오도 fixture 기반으로 고정하는 게 좋습니다. 🤖 Prompt for AI Agents |
||
| }); | ||
|
|
||
| describe("검색 영화 더보기 버튼이 숨겨지는지 테스트", () => { | ||
| describe("검색 영화 무한스크롤 테스트", () => { | ||
| beforeEach(() => { | ||
| cy.intercept( | ||
| "GET", | ||
| "https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=2", | ||
| { body: { results: [], total_pages: 1 } }, | ||
| ); | ||
|
|
||
| cy.intercept("GET", "**/search/movie*page=1*", { | ||
| fixture: "movies.json", | ||
| }).as("getMovies"); | ||
|
|
@@ -70,21 +80,21 @@ describe("검색 영화 더보기 버튼이 숨겨지는지 테스트", () => { | |
| cy.visit("http://localhost:5173"); | ||
| }); | ||
|
|
||
| it("마지막 페이지 도달 시 더보기 버튼이 사라진다", () => { | ||
| it("마지막 페이지 도달 시 스크롤 시에 영화를 더 불러오지 않는다.", () => { | ||
| cy.get(".search-input").type("영화"); | ||
| cy.get(".search-input").type("{enter}"); | ||
| cy.wait("@getMovies"); | ||
| cy.get("#load-movie-button").click(); | ||
| cy.get("#scroll-sentinel").scrollIntoView(); | ||
| cy.wait("@getMoviesPage2"); | ||
| cy.get("#load-movie-button").should("have.css", "display", "none"); | ||
| cy.get(".thumbnail-list li").should("have.length", 40); | ||
| }); | ||
| }); | ||
|
|
||
| describe("Skeleton UI 테스트", () => { | ||
| it("이미지 로드 전 스켈레톤 UI가 표시된다", () => { | ||
| cy.intercept( | ||
| "GET", | ||
| "https://api.themoviedb.org/3/movie/popular?language=en-US&page=1", | ||
| "https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=1", | ||
| { fixture: "movies.json" }, | ||
| ).as("getMovies"); | ||
|
|
||
|
|
@@ -110,7 +120,7 @@ describe("Skeleton UI 테스트", () => { | |
| it("이미지 로드 실패 시 스켈레톤 UI가 제거되고 대체 이미지가 표시된다", () => { | ||
| cy.intercept( | ||
| "GET", | ||
| "https://api.themoviedb.org/3/movie/popular?language=en-US&page=1", | ||
| "https://api.themoviedb.org/3/movie/popular?language=ko-KR&page=1", | ||
| { fixture: "movies.json" }, | ||
| ).as("getMovies"); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| describe("로컬스토리지 평점 저장 테스트", () => { | ||
| beforeEach(() => { | ||
| cy.clearLocalStorage(); | ||
| cy.intercept("GET", "**/movie/popular**", { fixture: "movies.json" }).as( | ||
| "getMovies", | ||
| ); | ||
| cy.intercept("GET", "**/movie/1001**", { fixture: "moviedetail.json" }).as( | ||
| "getMovieDetail", | ||
| ); | ||
| cy.visit("http://localhost:5173"); | ||
| cy.wait("@getMovies"); | ||
| cy.get(".thumbnail-list li").first().find(".item").click(); | ||
| cy.wait("@getMovieDetail"); | ||
| }); | ||
|
|
||
| it("별점을 클릭하면 로컬스토리지에 저장된다", () => { | ||
| cy.get(".my-rate-stars .my-star").eq(3).click(); | ||
| cy.window() | ||
| .its("localStorage") | ||
| .invoke("getItem", "movieRatings") | ||
| .then((val) => { | ||
| if (val) { | ||
| expect(JSON.parse(val)).to.deep.equal({ "1001": 8 }); | ||
| } | ||
| }); | ||
|
||
| }); | ||
|
||
|
|
||
| it("새로고침 후 같은 영화 모달을 열면 저장된 평점이 유지된다", () => { | ||
| cy.get(".my-rate-stars .my-star").eq(3).click(); | ||
| cy.reload(); | ||
| cy.wait("@getMovies"); | ||
| cy.get(".thumbnail-list li").first().find(".item").click(); | ||
| cy.wait("@getMovieDetail"); | ||
|
|
||
| cy.get(".my-rate-stars .my-star").each((star, index) => { | ||
| if (index <= 3) { | ||
| cy.wrap(star) | ||
| .should("have.attr", "src") | ||
| .and("include", "star_filled.png"); | ||
| } else { | ||
| cy.wrap(star) | ||
| .should("have.attr", "src") | ||
| .and("include", "star_empty.png"); | ||
| } | ||
| }); | ||
| cy.get(".my-score-label").should("contain", "재미있어요"); | ||
| cy.get(".my-rate-value").should("contain", "(8/10)"); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "id": 1001, | ||
| "title": "영화 1", | ||
| "poster_path": "/test0.jpg", | ||
| "backdrop_path": "/backdrop0.jpg", | ||
| "release_date": "2024-01-01", | ||
| "genres": [ | ||
| { "id": 28, "name": "액션" }, | ||
| { "id": 12, "name": "모험" } | ||
| ], | ||
| "vote_average": 7.5, | ||
| "overview": "테스트용 영화 줄거리입니다." | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: woowacourse/javascript-movie-review
Length of output: 957
🏁 Script executed:
Repository: woowacourse/javascript-movie-review
Length of output: 316
cy.visit()호출에서 프로토콜 누락으로 환경 의존성 발생cypress.config.ts에baseUrl이 설정되지 않았으므로,cy.visit()는 항상 완전한 URL(프로토콜 포함)을 필요로 합니다. 현재 라인 9, 14, 47에서cy.visit("localhost:5173")처럼 프로토콜 없이 작성되어 있어 테스트 실행이 불안정할 수 있습니다."http://localhost:5173"로 일관되게 작성되어 있습니다.두 가지 접근이 가능합니다:
cypress.config.ts에baseUrl을 설정하고cy.visit("/")로 통일하는 방식cy.visit()호출에 프로토콜을 명시하여 일관성 있게 작성하는 방식어느 방식을 선택하든 현재 3개 라인의 불일치를 해결해야 합니다.
🤖 Prompt for AI Agents