Skip to content
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

[스캇] 3, 4 단계 영화 티켓 예매 제출합니다. #39

Merged
merged 92 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
42a2343
docs: 기능 목록 정의
DYGames Apr 11, 2023
f8305d1
feat: Movie 클래스 구현
chws0508 Apr 11, 2023
aa6d728
feat: Reservation 클래스 정의
DYGames Apr 11, 2023
dc7fccd
feat: Moive List Item 뷰 구현
chws0508 Apr 11, 2023
c842836
feat: 예매 액티비티 레이아웃 구현
DYGames Apr 11, 2023
f502ff1
feat: ReservationResult 엑티비티 레이아웃 구현
chws0508 Apr 11, 2023
ffe8f7f
feat: 각 액티비티의 ActionBar에서 뒤로가기 버튼 구현
DYGames Apr 11, 2023
8362e18
refactor: 액티비티의 접미사로 Activity를 추가
DYGames Apr 11, 2023
238b904
feat: MainActivity에서 Movie ListView 구현
DYGames Apr 11, 2023
b4bc508
feat: MovieReservation 에서 movie의 정보를 받아와서 표시
chws0508 Apr 11, 2023
2740e57
feat: Counter 구현, 예약 정보 전달
DYGames Apr 11, 2023
2dd8f91
feat: ReservationResultActivity 로 정보 받아와서 표시
chws0508 Apr 11, 2023
1aac917
feat: 총 가격 계산, 상수 분리
DYGames Apr 11, 2023
b30fd27
feat: 할인 정책 추상화, 무비데이 할인 정책 구현
chws0508 Apr 12, 2023
066c2b9
feat: OffTime 할인 정책 구현
DYGames Apr 12, 2023
e9d0e8e
fix: LocalDateTime으로 변경하며 Date Formatting 방식 변경
DYGames Apr 12, 2023
b2f46a9
feat: 영화 예약시 할인 정책 적용 구현
DYGames Apr 12, 2023
d1cbeff
feat: 영화 날짜,시간 Spinner View 구현
chws0508 Apr 12, 2023
7eec62c
feat: 영화 시간 정책 구현
chws0508 Apr 12, 2023
c395e33
feat: Spinner에 날짜와 시간 표시하고, 원하는 시점에 선택한 정보를 가져올 수 있도록 구현
DYGames Apr 12, 2023
b109971
feat: Spinner에서 날짜와 시간 표시, 해당 날짜에 맞는 영화 시간대 표시
DYGames Apr 12, 2023
b7a9973
fix: 예약 페이지에서 스크롤이 정확하게 작동하지 않는 오류 수정
DYGames Apr 12, 2023
4506882
feat: 영화 예약 액티비티에서 savedInstanceState를 활용하여 데이터 유지
DYGames Apr 12, 2023
9c2f698
fix: 화면 초기화시 시간 스피너는 유지되지 않던 오류 수정
DYGames Apr 12, 2023
597148e
feat: Movie 도메인을 View로 렌더링 하는 기능 구현
chws0508 Apr 13, 2023
d0480c8
feat: Reservation 도메인을 View로 렌더링 하는 기능 구현
DYGames Apr 13, 2023
7ead53c
feat: GetSerializable 확장함수 구현
chws0508 Apr 13, 2023
0a01334
feat: Spinner를 각 Spinner 클래스에서 관리하게 분리
DYGames Apr 13, 2023
62568a0
refactor: WeekdayMovieTime 클래스명 변경
chws0508 Apr 13, 2023
1f22bc8
test: MovieTime에 대한 테스트 코드 작성
DYGames Apr 13, 2023
599308a
refactor: 테스트 코드에 대해 static method import로 변경
DYGames Apr 13, 2023
558d28e
fix: 회전시 카운터 값이 유지되지 않던 오류 수정
DYGames Apr 13, 2023
8672573
docs: 기능목록 수정
chws0508 Apr 13, 2023
8ce4ce8
refactor: activity, view 패키지 구분
chws0508 Apr 13, 2023
812864b
test: 테스트 라이브러리를 JUnit4로 변경
DYGames Apr 13, 2023
7821043
refactor: constrainLayout에서 match_parent 대신 0dp 를 사용하도록 수정, tools 를 이…
chws0508 Apr 14, 2023
7858f23
refactor: 기존 getSerializable 파일명을 전체적인 확장함수를 관리하는 파일인 UtilExtension으로…
chws0508 Apr 14, 2023
277138b
refactor: 무비 가상 데이터를 만드는 Object 생성
chws0508 Apr 14, 2023
d3fe0e0
refactor: ViewHolder를 사용, ClickEvent를 외부에서 주입
chws0508 Apr 15, 2023
284bcd6
refactor: Movie Key값을 Domain의 Movie모델에 작성
chws0508 Apr 15, 2023
6e885d5
refactor: DateSpinner 와 TimeSpinner 가 SaveStateSpinner 를 상속받도록 수정
chws0508 Apr 16, 2023
62b1c32
refactor: Counter 가 SaveStateTextView 를 상속받도록 수정 및 Counter의 Domain 요소…
chws0508 Apr 16, 2023
9cc9618
refactor: Discount가 할인된 Price를 리턴하도록 수정
chws0508 Apr 16, 2023
4366dad
feat: 예약을 생성하는 클래스 생성
chws0508 Apr 16, 2023
7868248
refactor: 모델 변경 사항 적용
chws0508 Apr 16, 2023
27b1c33
feat: Dto Model 생성
chws0508 Apr 16, 2023
1f83269
feat: DtoConverter 구현
chws0508 Apr 16, 2023
8115dc5
refactor: Dto 를 이용하여 Activity 끼리 데이터를 주고받도록 수정
chws0508 Apr 16, 2023
a5d819c
refactor: ReservationButton 삭제
chws0508 Apr 16, 2023
b717b08
refactor: 무비데이와 OffTime의 할인 조건을 동적으로 변경 가능하게 수정
chws0508 Apr 16, 2023
a5bc4e8
refactor: Domain model의 Serializable 제거
chws0508 Apr 16, 2023
83259a9
refactor: Movie의 picture 를 ImagePath로 수정
chws0508 Apr 16, 2023
98d3a62
refactor: Activity 생성을 생성할 Activity에게 책임을 부여
chws0508 Apr 18, 2023
26f7b4e
refactor: 네이밍 변경
chws0508 Apr 18, 2023
e0e2190
refactor: UI 관련 작업은 Dto모델로 처리하도록 수정
chws0508 Apr 18, 2023
bf7a3a7
refactor: 생성자에 넣지 않고, 함수 인자로 넣어 동적으로 UI를 그리도록 수정
chws0508 Apr 18, 2023
520f3ee
refactor: 도메인 구조 수정
chws0508 Apr 18, 2023
e649a46
feat: MovieDateTimePicker 구현
chws0508 Apr 18, 2023
0141e1a
refactor: 네이밍 변경
chws0508 Apr 19, 2023
f48d6cc
feat: 영화 데이터가 들어오지 않으면 앱을 종료시킨다
chws0508 Apr 19, 2023
81123ff
feat: 예약 정보가 들어오지 않으면 앱을 종료시킨다
chws0508 Apr 19, 2023
6604deb
refactor: DateTimePicker에서 date와 time을 가져오도록 수정
chws0508 Apr 19, 2023
435982e
refactor: domain 모듈 분리
chws0508 Apr 19, 2023
d32eda6
feat : 가능 목록 추가
chws0508 Apr 20, 2023
c344b4e
feat : 좌석 및 좌석 정책 구현
chws0508 Apr 20, 2023
a9647e4
feat : Tickets 구현 및 Ticket 구조 변경
chws0508 Apr 20, 2023
e91fbce
refactor : TicketOffice 생성 및 도메인 구조 변경
chws0508 Apr 22, 2023
9e0b445
refactor : ViewModel Mapper 구현
chws0508 Apr 22, 2023
35e2d0d
feat: 좌석 activity layout 구현
chws0508 Apr 22, 2023
413f8c7
feat: 좌석 생성 기능 구현
chws0508 Apr 22, 2023
a27d296
feat: 좌석 선택 Activity 구현
chws0508 Apr 22, 2023
b998054
feat: MoviesActivity 테스트 구현
chws0508 Apr 22, 2023
5e0078c
refactor: 변경사항 적용
chws0508 Apr 22, 2023
4523ce0
feat: 광고 layout 구현
chws0508 Apr 22, 2023
7294649
feat: recyclerView 구현
chws0508 Apr 22, 2023
a88d3d0
feat: 충돌 해결
chws0508 Apr 22, 2023
6f8c6a4
feat: 필요없는 파일 삭제
chws0508 Apr 22, 2023
4dfe4f0
feat: viewModel 네이밍 변경
chws0508 Apr 24, 2023
b65c290
refactor: ui모델을 movieDateTimePicker 에게 넘겨주도록 수정
chws0508 Apr 24, 2023
220cca0
refactor: movieDateTimePicker 에서 LocalDateTIme을 바로 반환하도록 수정
chws0508 Apr 24, 2023
9a7679a
refactor: 문자열 리소스에서 에러 문구 처리
chws0508 Apr 24, 2023
d39fed0
refactor: xml 에서 layout manager 설정
chws0508 Apr 24, 2023
765c2ba
refactor: viewType 을 enum으로 설정
chws0508 Apr 24, 2023
5d1c97a
refactor: Seat row 의 타입을 Character로 변환 및, row의 변환작업을 SeatUiModel 에서 해…
chws0508 Apr 24, 2023
9eb6ff2
refactor: 생성시점에 tickets를 주입하도록 수정
chws0508 Apr 24, 2023
ca6d2bf
refactor: 종료 메세지를 strings.xml 에 저장
chws0508 Apr 24, 2023
106ca61
refactor: Domain 변경을 필요할때만 하도록 수정
chws0508 Apr 24, 2023
271a18a
refactor: 더이상 ticketOffice 를 넘기지 않음
chws0508 Apr 25, 2023
6109357
refactor: TicketsUiModel 에서 view 를 그려주도록 변경
chws0508 Apr 25, 2023
efcc107
refactor: movieUiModel 에서 movie view 를 그려주도록 변경
chws0508 Apr 25, 2023
995605a
refactor: TicketOffice 에 Date 생성자 추가, tickets의 상태를 보고 UI 를 변경하도록 변경
chws0508 Apr 26, 2023
4dea2db
refactor: RankPolicy를 이용하지 않고, Rank 에서 조건에 맞는 Rank 를 반환하도록 수정
chws0508 Apr 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,19 @@ android {
kotlinOptions {
jvmTarget = "11"
}
testOptions {
animationsDisabled = true
}
}

dependencies {
implementation(project(":domain"))
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.0")
implementation("com.google.android.material:material:1.7.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation ("androidx.test.espresso:espresso-intents:3.4.0")
}
215 changes: 215 additions & 0 deletions app/src/androidTest/java/woowacourse/movie/SelectSeatActivityTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package woowacourse.movie

import android.content.Intent
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import woowacourse.movie.activity.ReservationResultActivity
import woowacourse.movie.activity.SelectSeatActivity
import woowacourse.movie.view.model.*
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime

@RunWith(AndroidJUnit4::class)
class SelectSeatActivityTest {
private val movieUiModel = MovieUiModel(0, "해리포터", LocalDate.MAX, LocalDate.MIN, 0, "")
private val date = LocalDate.of(2023, 4, 22)
private val time = LocalTime.of(9, 0)
private val dateTime: LocalDateTime = LocalDateTime.of(date, time)
private val ticketDateUiModel = TicketDateUiModel(dateTime)

private val intent =
Intent(ApplicationProvider.getApplicationContext(), SelectSeatActivity::class.java).apply {
putExtra("movie", movieUiModel)
putExtra("peopleCount", 3)
putExtra("ticket", ticketDateUiModel)
}

@get:Rule
val activityRule = ActivityScenarioRule<SelectSeatActivity>(intent)

@Test
fun check_seats_created() {
// given
val seatFirst = onView(withText("A1"))
val seatLast = onView(withText("E4"))
// then
seatFirst.check(matches(isDisplayed()))
seatLast.check(matches(isDisplayed()))
}

@Test
fun 선택되지_않았던_좌석을_클릭했을때_선택된_상태로_바뀐다(){
// given
val seat = onView(withText("A1"))
// when
seat.perform(click())
// then
seat.check(matches(isSelected()))
}

@Test
fun 선택했던_좌석을_클릭했을때_선택하지_않은_상태로_바뀐다(){
// given
val seat = onView(withText("A1"))
// when
seat.perform(click())
seat.perform(click())
// then
seat.check(matches(isNotSelected()))
}

@Test
fun 인원수와_같은_수만큼_좌석을_클릭하면_더이상_좌석이_선택된_상태로_변경되지_않는다(){
// given
val seat1 = onView(withText("A1"))
val seat2 = onView(withText("A2"))
val seat3 = onView(withText("A3"))
val seat4 = onView(withText("B4"))
// when
seat1.perform(click())
seat2.perform(click())
seat3.perform(click())
seat4.perform(click())
// then
seat4.check(matches(isNotSelected()))
}

@Test
fun 조조할인을_받고_B등급_좌석을_클릭하면_가격텍스트가_8000원_으로_바뀐다(){
// given
val seat = onView(withText("A1"))
val price = onView(withId(R.id.select_seat_price_text_view))
// when
seat.perform(click())
// then
price.check(matches(withText("8,000원")))
}

@Test
fun 조조할인을_받고_A등급_좌석을_클릭하면_가격텍스트가_10000원_으로_바뀐다(){
// given
val seat = onView(withText("E1"))
val price = onView(withId(R.id.select_seat_price_text_view))
// when
seat.perform(click())
// then
price.check(matches(withText("10,000원")))
}

@Test
fun 조조할인을_받고_S등급_좌석을_클릭하면_가격텍스트가_13000원_으로_바뀐다(){
// given
val seat = onView(withText("C1"))
val price = onView(withId(R.id.select_seat_price_text_view))
// when
seat.perform(click())
// then
price.check(matches(withText("13,000원")))
}

@Test
fun 조조할인을_받고_S등급_좌석과_A등급_좌석을_클릭하면_가격텍스트가_23000원_으로_바뀐다(){
// given
val seatS = onView(withText("C1"))
val seatA = onView(withText("E1"))
val price = onView(withId(R.id.select_seat_price_text_view))
// when
seatS.perform(click())
seatA.perform(click())
// then
price.check(matches(withText("23,000원")))
}

@Test
fun 인원수와_같은_수만큼_좌석이_선택된_상태가_아니라면_버튼을_클릭할_수_없다(){
// given
val seat1 = onView(withText("A1"))
val seat2 = onView(withText("A2"))
val button = onView(withText("확인"))
// when
seat1.perform(click())
seat2.perform(click())
// then
button.check(matches(isNotClickable()))
}

@Test
fun 인원수와_같은_수만큼_좌석이_선택된_상태이면_버튼을_클릭할_수_있다(){
// given
val seat1 = onView(withText("A1"))
val seat2 = onView(withText("A2"))
val seat3 = onView(withText("A3"))
val button = onView(withText("확인"))
// when
seat1.perform(click())
seat2.perform(click())
seat3.perform(click())
// then
button.check(matches(isClickable()))
}

@Test
fun 인원수와_같은_수만큼_좌석이_선택된_상태에서_버튼을_클릭하면_다이얼로그가_나온다(){
// given
val seat1 = onView(withText("A1"))
val seat2 = onView(withText("A2"))
val seat3 = onView(withText("A3"))
val button = onView(withText("확인"))
// when
seat1.perform(click())
seat2.perform(click())
seat3.perform(click())
button.perform(click())
// then
onView(withText(R.string.select_seat_dialog_title)).check(matches(isDisplayed()))
}

@Test
fun 다이얼로그가_나온_상태에서_배경을_클릭해도_다이얼로그가_사라지지_않는다(){
// given
val seat1 = onView(withText("A1"))
val seat2 = onView(withText("A2"))
val seat3 = onView(withText("A3"))
val button = onView(withText("확인"))
// when
seat1.perform(click())
seat2.perform(click())
seat3.perform(click())
button.perform(click())
val dialog = onView(withText(R.string.select_seat_dialog_title))
onView(isRoot()).perform(click())
// then
(dialog).check(matches(isDisplayed()))
}

@Test
fun 다이얼로그가_나온_상태에서_예매확인을_클릭하면_예매결과창으로_넘어간다(){
// given
Intents.init()
val seat1 = onView(withText("A1"))
val seat2 = onView(withText("A2"))
val seat3 = onView(withText("A3"))
val button = onView(withText("확인"))
val dialogPositiveButton = onView(withText("예매 완료"))
// when
seat1.perform(click())
seat2.perform(click())
seat3.perform(click())
button.perform(click())
dialogPositiveButton.perform(click())
// then
Intents.intended(IntentMatchers.hasComponent(ReservationResultActivity::class.java.name))
Intents.release()
}
}
6 changes: 5 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
android:supportsRtl="true"
android:theme="@style/Theme.Movie"
tools:targetApi="31">
<activity
android:name=".activity.SelectSeatActivity"
android:exported="false">
</activity>
<activity
android:name=".activity.ReservationResultActivity"
android:exported="false" />
<activity
android:name=".activity.MovieReservationActivity"
android:exported="true" />
<activity
android:name=".activity.MainActivity"
android:name=".activity.MoviesActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package woowacourse.movie

import woowacourse.movie.view.model.AdvertisementUiModel

object MockAdvertisementFactory {
fun generateAdvertisement(): AdvertisementUiModel {
return AdvertisementUiModel(R.drawable.advertisement, "https://www.naver.com")
}
}
14 changes: 7 additions & 7 deletions app/src/main/java/woowacourse/movie/MockMoviesFactory.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
package woowacourse.movie

import woowacourse.movie.domain.DateRange
import woowacourse.movie.domain.Movie
import woowacourse.movie.domain.Movies
import domain.DateRange
import domain.Movie
import domain.Movies
import java.time.LocalDate

object MockMoviesFactory {
fun generateMovies(): Movies {
return Movies(
listOf(generateMovie())
List(1000) { (generateMovie(it)) }
)
}

private fun generateMovie(): Movie {
private fun generateMovie(number: Int): Movie {
return Movie(
R.drawable.poster_harrypotter.toString(),
"해리 포터",
"해리 포터${number}",
DateRange(
LocalDate.of(2024, 3, 1),
LocalDate.of(2024, 3, 31),
),
153,
"adsfasdfadsf",
"《해리 포터》(Harry Potter)는 1997년부터 2016년까지 연재된 영국의 작가 J. K. 롤링의 판타지 소설 시리즈이다. 유일한 친척인 이모네 집 계단 밑 벽장에서 생활하던 11살 소년 해리 포터가 호그와트 마법학교에 다니면서 겪게 되는 판타지 이야기를 그리고 있다.",
)
}
}
6 changes: 6 additions & 0 deletions app/src/main/java/woowacourse/movie/UtilExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package woowacourse.movie

import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.core.content.ContextCompat
import java.io.Serializable

inline fun <reified T : Serializable> Bundle.getSerializableCompat(key: String): T? {
Expand All @@ -11,3 +13,7 @@ inline fun <reified T : Serializable> Bundle.getSerializableCompat(key: String):
getSerializable(key) as? T
}
}

fun View.setBackgroundColorId(color: Int) {
setBackgroundColor(ContextCompat.getColor(context, color))
}
23 changes: 0 additions & 23 deletions app/src/main/java/woowacourse/movie/activity/MainActivity.kt

This file was deleted.

Loading