From 9ecf99c9c183eb5974968d3b38f26e1ee8ba3232 Mon Sep 17 00:00:00 2001 From: HiHoi Date: Wed, 27 Mar 2024 17:24:32 +0900 Subject: [PATCH 1/6] feat: Add CalendarVM and connect CalendarView --- HANE24.xcodeproj/project.pbxproj | 4 + HANE24/View/Calendar/CalendarBodyView.swift | 9 +- HANE24/View/Calendar/CalendarGridView.swift | 28 ++--- HANE24/View/Calendar/CalendarHeaderView.swift | 14 +-- HANE24/View/Calendar/CalendarView.swift | 42 ++------ HANE24/View/Calendar/TagLogView.swift | 10 +- HANE24/ViewModel/CalendarVM.swift | 101 ++++++++++++++++++ HANE24/ViewModel/NetworkManager.swift | 22 ++-- HANE24TEST/HANE24Test.swift | 40 +++++-- 9 files changed, 194 insertions(+), 76 deletions(-) create mode 100644 HANE24/ViewModel/CalendarVM.swift diff --git a/HANE24.xcodeproj/project.pbxproj b/HANE24.xcodeproj/project.pbxproj index 842aa55..5e861ba 100644 --- a/HANE24.xcodeproj/project.pbxproj +++ b/HANE24.xcodeproj/project.pbxproj @@ -56,6 +56,7 @@ 9AF730F8299E2F5000AF2E53 /* CalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF730F7299E2F5000AF2E53 /* CalendarView.swift */; }; 9AF730FB299F53C700AF2E53 /* HaneVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF730FA299F53C700AF2E53 /* HaneVM.swift */; }; 9AF730FD299F602D00AF2E53 /* JSONs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AF730FC299F602D00AF2E53 /* JSONs.swift */; }; + D6185AE12BB3C71800E6944A /* CalendarVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6185AE02BB3C71800E6944A /* CalendarVM.swift */; }; D646BD0C2B95DCD500ED631E /* HANE24Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = D646BD0B2B95DCD500ED631E /* HANE24Test.swift */; }; /* End PBXBuildFile section */ @@ -142,6 +143,7 @@ 9AF730FA299F53C700AF2E53 /* HaneVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HaneVM.swift; sourceTree = ""; }; 9AF730FC299F602D00AF2E53 /* JSONs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONs.swift; sourceTree = ""; }; A021B0070CB31045F069E3A2 /* Pods-24HANE.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-24HANE.release.xcconfig"; path = "Target Support Files/Pods-24HANE/Pods-24HANE.release.xcconfig"; sourceTree = ""; }; + D6185AE02BB3C71800E6944A /* CalendarVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarVM.swift; sourceTree = ""; }; D646BD092B95DCD500ED631E /* HANE24Test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HANE24Test.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D646BD0B2B95DCD500ED631E /* HANE24Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HANE24Test.swift; sourceTree = ""; }; D680AC322BB17CA00083025D /* env.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = env.xcconfig; sourceTree = ""; }; @@ -316,6 +318,7 @@ isa = PBXGroup; children = ( 9AF730FA299F53C700AF2E53 /* HaneVM.swift */, + D6185AE02BB3C71800E6944A /* CalendarVM.swift */, 0E3ED8A72BB13727001B0BAE /* NetworkManager.swift */, 0E6B608E29AC850D009D8BC4 /* NetworkMonitoringManager.swift */, ); @@ -541,6 +544,7 @@ 0E6B608F29AC850D009D8BC4 /* NetworkMonitoringManager.swift in Sources */, 2B1326132B285B1D00301A8B /* NoticeView.swift in Sources */, 0E1654F5299A285B001E5EED /* ContentView.swift in Sources */, + D6185AE12BB3C71800E6944A /* CalendarVM.swift in Sources */, 9AF730EF299D3A4900AF2E53 /* CalendarGridView.swift in Sources */, 0E3ED8A82BB13727001B0BAE /* NetworkManager.swift in Sources */, 0E9868252B2B6C0B00E127DC /* CalendarHeaderView.swift in Sources */, diff --git a/HANE24/View/Calendar/CalendarBodyView.swift b/HANE24/View/Calendar/CalendarBodyView.swift index 1690876..4f3a415 100644 --- a/HANE24/View/Calendar/CalendarBodyView.swift +++ b/HANE24/View/Calendar/CalendarBodyView.swift @@ -8,7 +8,7 @@ import SwiftUI struct CalendarBodyView: View { - @EnvironmentObject var hane: Hane + @EnvironmentObject var calendarVM: CalendarVM @State var picker = false @State var datePickerSelection: Date @@ -42,9 +42,9 @@ struct CalendarBodyView: View { } } } - .onChange(of: picker) {pickerState in + .onChange(of: picker) { pickerState in if !pickerState { - hane.selectedDate = datePickerSelection + calendarVM.calendarModel.selectedDate = datePickerSelection } } } @@ -52,5 +52,6 @@ struct CalendarBodyView: View { #Preview { CalendarBodyView(datePickerSelection: Date()) - .environmentObject(Hane()) + .environmentObject(CalendarVM()) +// .environmentObject(Hane()) } diff --git a/HANE24/View/Calendar/CalendarGridView.swift b/HANE24/View/Calendar/CalendarGridView.swift index df027c2..1d7d3a8 100644 --- a/HANE24/View/Calendar/CalendarGridView.swift +++ b/HANE24/View/Calendar/CalendarGridView.swift @@ -10,7 +10,8 @@ import SwiftUI struct CalendarGridView: View { @Binding var picker: Bool - @EnvironmentObject var hane: Hane + @EnvironmentObject var calendarVM: CalendarVM +// @EnvironmentObject var hane: Hane let weekdays = ["일", "월", "화", "수", "목", "금", "토"] let cols: [GridItem] = Array(repeating: GridItem(.flexible(), spacing: 20), count: 7) @@ -18,7 +19,7 @@ struct CalendarGridView: View { var body: some View { ZStack { LoadingAnimation() - .isHidden(!hane.loading) + .isHidden(!calendarVM.loading) VStack { // day of week LazyVGrid(columns: cols, spacing: 12) { @@ -35,17 +36,17 @@ struct CalendarGridView: View { // is today ? border only // default LazyVGrid(columns: cols, spacing: 12) { - ForEach(hane.selectedDate.daysOfMonth.indices, id: \.self) { d in - if let day = hane.selectedDate.daysOfMonth[d] { + ForEach(calendarVM.calendarModel.selectedDate.daysOfMonth.indices, id: \.self) { d in + if let day = calendarVM.calendarModel.selectedDate.daysOfMonth[d] { Button { - hane.selectedDate = day + calendarVM.calendarModel.selectedDate = day } label: { ZStack { - RoundedRectangle(cornerRadius: day.isSameDate(with: hane.selectedDate) ? 20 : 10) + RoundedRectangle(cornerRadius: day.isSameDate(with: calendarVM.calendarModel.selectedDate) ? 20 : 10) .foregroundColor(getGridColor(day)) .overlay { if day.isSameDate(with: Date()) - && !day.isSameDate(with: hane.selectedDate) { + && !day.isSameDate(with: calendarVM.calendarModel.selectedDate) { RoundedRectangle(cornerRadius: 10) .stroke(Color.dateToday, lineWidth: 1) } @@ -54,7 +55,7 @@ struct CalendarGridView: View { Text("\(day.dayToInt)") .foregroundColor(getTextColor(day)) - .font(.system(size: 14, weight: day.isSameDate(with: hane.selectedDate) ? .bold : .regular)) + .font(.system(size: 14, weight: day.isSameDate(with: calendarVM.calendarModel.selectedDate) ? .bold : .regular)) } } .frame(width: 30, height: 30) @@ -64,19 +65,19 @@ struct CalendarGridView: View { } } } - .isHidden(hane.loading) + .isHidden(calendarVM.loading) } } } func getGridColor(_ day: Date) -> Color { switch day { - case day where day.isSameDate(with: hane.selectedDate): + case day where day.isSameDate(with: calendarVM.calendarModel.selectedDate): return .dateSelected case day where day.isSameDate(with: Date.now): return .backgroundCalendar default: - return calculateLogColor(accumulationTime: hane.dailyTotalTimesInAMonth[day.dayToInt]) + return calculateLogColor(accumulationTime: calendarVM.calendarModel.dailyTotalTimesInAMonth[day.dayToInt]) } } @@ -84,7 +85,7 @@ struct CalendarGridView: View { switch day { case day where day > Date.now: return .fontDisabled - case day where day.isSameDate(with: hane.selectedDate): + case day where day.isSameDate(with: calendarVM.calendarModel.selectedDate): return .fontWhite case day where day.isSameDate(with: Date.now): return .dateToday @@ -112,5 +113,6 @@ struct CalendarGridView: View { #Preview { CalendarGridView(picker: .constant(false)) - .environmentObject(Hane()) + .environmentObject(CalendarVM()) +// .environmentObject(Hane()) } diff --git a/HANE24/View/Calendar/CalendarHeaderView.swift b/HANE24/View/Calendar/CalendarHeaderView.swift index 91abbde..e22d0cc 100644 --- a/HANE24/View/Calendar/CalendarHeaderView.swift +++ b/HANE24/View/Calendar/CalendarHeaderView.swift @@ -9,28 +9,29 @@ import SwiftUI struct CalendarHeaderView: View { @Binding var picker: Bool - @EnvironmentObject var hane: Hane +// @EnvironmentObject var hane: Hane + @EnvironmentObject var calendarVM: CalendarVM var body: some View { HStack { changeMonthButton(isForward: false) - .disabled(hane.selectedDate.toString("yyyy.MM") <= "2022.08" || hane.loading) + .disabled(calendarVM.calendarModel.selectedDate.toString("yyyy.MM") <= "2022.08" || calendarVM.loading) Spacer() - Text("\(hane.selectedDate.yearToString).\(hane.selectedDate.monthToString)") + Text("\(calendarVM.calendarModel.selectedDate.yearToString).\(calendarVM.calendarModel.selectedDate.monthToString)") .foregroundColor(picker ? .gradientPurple : .fontDefault ) .onTapGesture { picker.toggle() } Spacer() changeMonthButton(isForward: true) - .disabled(hane.selectedDate.toString("yyyy.MM") >= Date().toString("yyyy.MM") || hane.loading) + .disabled(calendarVM.calendarModel.selectedDate.toString("yyyy.MM") >= Date().toString("yyyy.MM") || calendarVM.loading) } .font(.system(size: 20, weight: .semibold)) } @ViewBuilder func changeMonthButton(isForward: Bool) -> some View { Button { - hane.selectedDate = Calendar.current.date(byAdding: .month, value: isForward ? 1 : -1, to: hane.selectedDate)! + calendarVM.calendarModel.selectedDate = Calendar.current.date(byAdding: .month, value: isForward ? 1 : -1, to: calendarVM.calendarModel.selectedDate)! } label: { ZStack { Image(systemName: isForward ? "chevron.right" : "chevron.left") @@ -44,5 +45,6 @@ struct CalendarHeaderView: View { #Preview { CalendarHeaderView(picker: .constant(false)) - .environmentObject(Hane()) + .environmentObject(CalendarVM()) +// .environmentObject(Hane()) } diff --git a/HANE24/View/Calendar/CalendarView.swift b/HANE24/View/Calendar/CalendarView.swift index 95d8dbb..8d3db57 100644 --- a/HANE24/View/Calendar/CalendarView.swift +++ b/HANE24/View/Calendar/CalendarView.swift @@ -10,7 +10,8 @@ import SwiftUI /// selectedDate: Date = 선택 날짜 struct CalendarView: View { @Environment(\.colorScheme) var colorScheme - @EnvironmentObject var hane: Hane +// @EnvironmentObject var hane: Hane + @EnvironmentObject var calendarVM: CalendarVM var body: some View { ZStack { @@ -19,16 +20,17 @@ struct CalendarView: View { ScrollView { PullToRefresh(coordinateSpaceName: "pullToRefresh") { Task { - try await hane.refresh() + try await calendarVM.updateMonthlyLogs(date: calendarVM.calendarModel.selectedDate) } } VStack(spacing: 16) { - CalendarBodyView(datePickerSelection: hane.selectedDate) + CalendarBodyView(datePickerSelection: calendarVM.calendarModel.selectedDate) .padding(.horizontal, 5) - AccTimeCardForCalendarView(totalAccTime: hane.monthlyTotalAccumulationTime, - validAccTime: hane.monthlyAcceptedAccumulationTime ) + AccTimeCardForCalendarView( + totalAccTime: calendarVM.calendarModel.monthlyTotalAccumulationTime, + validAccTime: calendarVM.calendarModel.monthlyAcceptedAccumulationTime) .padding(.vertical, 10) - TagLogView(logList: convert(hane.monthlyLogs[hane.selectedDate.toString("yyyy.MM.dd")] ?? [])) + TagLogView(logList: calendarVM.convert(calendarVM.calendarModel.monthlyLogs[calendarVM.calendarModel.selectedDate.toString("yyyy.MM.dd")] ?? [])) .padding(.top, 10) Spacer() } @@ -37,39 +39,17 @@ struct CalendarView: View { .coordinateSpace(name: "pullToRefresh") } .coordinateSpace(name: "pullToRefresh") - .onChange(of: hane.selectedDate) {[oldDate = hane.selectedDate] newDate in + .onChange(of: calendarVM.calendarModel.selectedDate) {[oldDate = calendarVM.calendarModel.selectedDate] newDate in if oldDate.monthToInt != newDate.monthToInt || oldDate.yearToInt != newDate.yearToInt { Task { - try await hane.updateMonthlyLogs(date: newDate) + try await calendarVM.updateMonthlyLogs(date: newDate) } } } } - - func convert(_ from: [InOutLog]) -> [Log] { - guard !from.isEmpty else { return [] } - var logArray = from.map { - var inTime: String? - var outTime: String? - var logTime: String? = "누락" - if let intime = $0.inTimeStamp { - inTime = Date(milliseconds: intime).toString("HH:mm:ss") - } - if let outtime = $0.outTimeStamp { - outTime = Date(milliseconds: outtime).toString("HH:mm:ss") - } - if var logtime = $0.durationSecond { - logtime -= 9 * 3600 - logTime = Date(milliseconds: logtime).toString("HH:mm:ss") - } - return Log(inTime: inTime, outTime: outTime, logTime: logTime) - } - logArray[0].logTime = (logArray[0].logTime == "누락" && hane.selectedDate.toString("yyyy.MM.dd") == Date().toString("yyyy.MM.dd")) ? "-" : logArray[0].logTime - return logArray.reversed() - } } #Preview { CalendarView() - .environmentObject(Hane()) + .environmentObject(CalendarVM()) } diff --git a/HANE24/View/Calendar/TagLogView.swift b/HANE24/View/Calendar/TagLogView.swift index 9d4c53f..653cb51 100644 --- a/HANE24/View/Calendar/TagLogView.swift +++ b/HANE24/View/Calendar/TagLogView.swift @@ -8,16 +8,17 @@ import SwiftUI struct TagLogView: View { - @EnvironmentObject var hane: Hane +// @EnvironmentObject var hane: Hane + @EnvironmentObject var calendarVM: CalendarVM @Environment(\.colorScheme) var colorScheme var logList: [Log] var body: some View { - let dailyTotalTime = hane.dailyTotalTimesInAMonth[hane.selectedDate.dayToInt] + let dailyTotalTime = calendarVM.calendarModel.dailyTotalTimesInAMonth[calendarVM.calendarModel.selectedDate.dayToInt] VStack(alignment: .center, spacing: 4) { HStack { - Text("\(hane.selectedDate.monthToInt).\(hane.selectedDate.dayToInt) \(hane.selectedDate.toString("E"))요일") + Text("\(calendarVM.calendarModel.selectedDate.monthToInt).\(calendarVM.calendarModel.selectedDate.dayToInt) \(calendarVM.calendarModel.selectedDate.toString("E"))요일") .padding(.leading, 5) Spacer() Text("\(dailyTotalTime / 3600)시간 \((dailyTotalTime % 3600) / 60)분") @@ -92,5 +93,6 @@ struct TagLogView: View { #Preview { TagLogView(logList: []) - .environmentObject(Hane()) + .environmentObject(CalendarVM()) +// .environmentObject(Hane()) } diff --git a/HANE24/ViewModel/CalendarVM.swift b/HANE24/ViewModel/CalendarVM.swift new file mode 100644 index 0000000..c786acd --- /dev/null +++ b/HANE24/ViewModel/CalendarVM.swift @@ -0,0 +1,101 @@ +// +// CalendarVM.swift +// 24HANE +// +// Created by Hosung Lim on 3/27/24. +// + +import Foundation + +protocol CalendarDataProtocol {} + +protocol CalendarFetchProtocol {} + +protocol CalendarProtocol {} + +struct CalendarModel { + var selectedDate: Date = .now + var monthlyTotalAccumulationTime: Int64 = 0 + var monthlyAcceptedAccumulationTime: Int64 = 0 + var monthlyLogs: [String: [InOutLog]] = [:] + var dailyTotalTimesInAMonth: [Int64] = Array(repeating: 0, count: 32) +} + +class CalendarVM: ObservableObject, CalendarProtocol { + // 네트워크VM 객체 + private var network: NetworkProtocol + + // 사용할 날짜 데이터 + @Published var calendarModel: CalendarModel = CalendarModel() + @Published var loading = false + + // 데이터를 갱신하거나 불러오는 함수 + + func getPerMonth(year: Int, month: Int) async throws -> PerMonth { + var components = URLComponents(string: network.apiRoot + "/v3/tag-log/getAllTagPerMonth")! + let year = URLQueryItem(name: "year", value: "\(year)") + let month = URLQueryItem(name: "month", value: "\(month)") + components.queryItems = [year, month] + + guard let perMonth = try await network.getRequest(components.url!.absoluteString, type: PerMonth.self) else { + fatalError() + } + return perMonth + } + + func updateMonthlyLogs(date: Date) async throws { + self.loading = true + + // update MonthlyLogs + let perMonth: PerMonth = try await getPerMonth(year: date.yearToInt, month: date.monthToInt) + + calendarModel.monthlyLogs = Dictionary(grouping: perMonth.inOutLogs) { + Date(milliseconds: $0.inTimeStamp ?? $0.outTimeStamp!).toString("yyyy.MM.dd") + } + + // update Daily Total Accumulation Times (CalendarView) + calendarModel.dailyTotalTimesInAMonth = Array(repeating: 0, count: 32) + for dailyLog in calendarModel.monthlyLogs { + var sum: Int64 = 0 + for log in dailyLog.value { + sum += log.durationSecond ?? 0 + } + calendarModel.dailyTotalTimesInAMonth[Int(dailyLog.key.split(separator: ".")[2]) ?? 0] = sum + } + + calendarModel.monthlyTotalAccumulationTime = perMonth.totalAccumulationTime + calendarModel.monthlyAcceptedAccumulationTime = perMonth.acceptedAccumulationTime + + self.loading = false + } + + // 보여줄 문자를 파싱하는 함수들 + + func convert(_ from: [InOutLog]) -> [Log] { + guard !from.isEmpty else { return [] } + print(from) + var logArray = from.map { + var inTime: String? + var outTime: String? + var logTime: String? = "누락" + if let intime = $0.inTimeStamp { + inTime = Date(milliseconds: intime).toString("HH:mm:ss") + } + if let outtime = $0.outTimeStamp { + outTime = Date(milliseconds: outtime).toString("HH:mm:ss") + } + if var logtime = $0.durationSecond { + logtime -= 9 * 3600 + logTime = Date(milliseconds: logtime).toString("HH:mm:ss") + } + return Log(inTime: inTime, outTime: outTime, logTime: logTime) + } + logArray[0].logTime = (logArray[0].logTime == "누락" && calendarModel.selectedDate.toString("yyyy.MM.dd") == Date().toString("yyyy.MM.dd")) ? "-" : logArray[0].logTime + return logArray.reversed() + } + + // 초기화 + init(network: NetworkProtocol = NetworkManager.shared) { + self.network = network + } +} diff --git a/HANE24/ViewModel/NetworkManager.swift b/HANE24/ViewModel/NetworkManager.swift index c526dea..746c290 100644 --- a/HANE24/ViewModel/NetworkManager.swift +++ b/HANE24/ViewModel/NetworkManager.swift @@ -18,17 +18,17 @@ protocol NetworkProtocol { } class NetworkManager: NetworkProtocol { - - let shared = NetworkManager() - + + static let shared = NetworkManager() + var session: URLSession var apiRoot: String - + private init(session: URLSession = URLSession.shared) { self.session = session self.apiRoot = "https://" + (Bundle.main.infoDictionary?["API_URL"] as? String ?? "wrong") } - + func getRequest(_ urlPath: String, type: T.Type) async throws -> T? where T : Decodable { guard let url = URL(string: apiRoot + urlPath) else { /// FIXME: invalid URL의 경우 error handling @@ -51,9 +51,8 @@ class NetworkManager: NetworkProtocol { let decodedData = try JSONDecoder().decode(type.self, from: data) return decodedData } - -// MARK: post, patch, delete의 경우 httpMethod를 제외하고 로직이 동일함 -> request with return value, request without return value로 나눠서 method 방식을 전달받는건 어떤지? - + + // MARK: post, patch, delete의 경우 httpMethod를 제외하고 로직이 동일함 -> request with return value, request without return value로 나눠서 method 방식을 전달받는건 어떤지? func postRequest(_ urlPath: String) async throws { guard let url = URL(string: apiRoot + urlPath) else { return @@ -61,7 +60,7 @@ class NetworkManager: NetworkProtocol { guard let token = UserDefaults.standard.string(forKey: "Token") else { throw MyError.tokenExpired("get new tokenn") } - + var request = URLRequest(url: url) request.httpMethod = "POST" request.allHTTPHeaderFields = [ @@ -71,7 +70,7 @@ class NetworkManager: NetworkProtocol { throw MyError.tokenExpired("request Failed") } } - + func patchRequest(_ urlPath: String) async throws { guard let url = URL(string: apiRoot + urlPath) else { return @@ -79,7 +78,6 @@ class NetworkManager: NetworkProtocol { guard let token = UserDefaults.standard.string(forKey: "Token") else { throw MyError.tokenExpired("get new tokenn") } - var request = URLRequest(url: url) request.httpMethod = "PATCH" request.allHTTPHeaderFields = [ @@ -97,7 +95,7 @@ class NetworkManager: NetworkProtocol { guard let token = UserDefaults.standard.string(forKey: "Token") else { throw MyError.tokenExpired("get new tokenn") } - + var request = URLRequest(url: url) request.httpMethod = "DELETE" request.allHTTPHeaderFields = [ diff --git a/HANE24TEST/HANE24Test.swift b/HANE24TEST/HANE24Test.swift index 3a46f1d..61a5c33 100644 --- a/HANE24TEST/HANE24Test.swift +++ b/HANE24TEST/HANE24Test.swift @@ -71,23 +71,51 @@ let answer = [Log(inTime: Optional("12:14:39"), outTime: Optional("16:42:19"), l */ +class MockNetwork: NetworkProtocol { + static var shared = MockNetwork() + + var session: URLSession + + var apiRoot: String = "" + + func getRequest(_ urlPath: String, type: T.Type) async throws -> T? where T : Decodable { + return nil + } + + func postRequest(_ urlPath: String) async throws { + return + } + + func patchRequest(_ urlPath: String) async throws { + return + } + + func deleteRequest(_ urlPath: String) async throws { + return + } + + private init(session: URLSession = URLSession.shared) { + self.session = session + } +} + final class HaneCalendarTest: XCTestCase { // ViewModel var sut: Hane! // CalendarView 안에 있는 convert 함수를 테스트하기 위해 View 객체 생성 - var calendarView: CalendarView! + var calendarVM: CalendarVM! // 테스트 객체 초기화 override func setUpWithError() throws { try super.setUpWithError() sut = Hane() - calendarView = CalendarView() + calendarVM = CalendarVM(network: MockNetwork.shared) } // 테스트 이후 객체 소멸 override func tearDownWithError() throws { - calendarView = nil + calendarVM = nil sut = nil try super.tearDownWithError() } @@ -104,7 +132,7 @@ final class HaneCalendarTest: XCTestCase { } // when - let parsedData = calendarView.convert(sut.perMonth.inOutLogs) + let parsedData = calendarVM.convert(sut.perMonth.inOutLogs) // 질문사항 1. convert 함수가 왜 calendarView에 종속되어 있는지 // then @@ -123,7 +151,7 @@ final class HaneCalendarTest: XCTestCase { } // when - let parsedData = calendarView.convert(sut.perMonth.inOutLogs) + let parsedData = calendarVM.convert(sut.perMonth.inOutLogs) // then XCTAssertEqual(parsedData, []) @@ -141,7 +169,7 @@ final class HaneCalendarTest: XCTestCase { } // when - let parsedData = calendarView.convert(sut.perMonth.inOutLogs) + let parsedData = calendarVM.convert(sut.perMonth.inOutLogs) let parsedDataFirst = parsedData[0] // then From ade4d8352a14e66f728e064022b0ac98ee5868ef Mon Sep 17 00:00:00 2001 From: HiHoi Date: Wed, 27 Mar 2024 19:06:27 +0900 Subject: [PATCH 2/6] WIP --- HANE24/ContentView.swift | 2 +- HANE24/HANE24App.swift | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/HANE24/ContentView.swift b/HANE24/ContentView.swift index 1f706d1..475d06e 100644 --- a/HANE24/ContentView.swift +++ b/HANE24/ContentView.swift @@ -36,7 +36,7 @@ struct ContentView: View { } do { - try hane.isSignIn = await hane.isLogin() ? true : false + try hane.isSignIn = await hane.isLogin() ? true : false self.signInChecked = true } catch { print("Invalid URL") diff --git a/HANE24/HANE24App.swift b/HANE24/HANE24App.swift index 1076a02..038ca20 100644 --- a/HANE24/HANE24App.swift +++ b/HANE24/HANE24App.swift @@ -11,11 +11,13 @@ import SwiftUI struct HANE24App: App { var hane = Hane() + var calendar = CalendarVM() var body: some Scene { WindowGroup { ContentView() .environmentObject(hane) + .environmentObject(calendar) } } } From 1e3b9d17900c27018bea8c023d46b8187a70d4b0 Mon Sep 17 00:00:00 2001 From: HiHoi Date: Wed, 27 Mar 2024 20:15:07 +0900 Subject: [PATCH 3/6] feat: check simulator action --- HANE24.xcodeproj/project.pbxproj | 8 +++++--- HANE24/View/MainView.swift | 3 +++ HANE24/ViewModel/CalendarVM.swift | 8 ++++---- HANE24/ViewModel/HaneVM.swift | 2 +- HANE24/ViewModel/NetworkManager.swift | 1 + Podfile.lock | 2 +- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/HANE24.xcodeproj/project.pbxproj b/HANE24.xcodeproj/project.pbxproj index 5e861ba..cf7e214 100644 --- a/HANE24.xcodeproj/project.pbxproj +++ b/HANE24.xcodeproj/project.pbxproj @@ -131,9 +131,9 @@ 0EFDFD46299F5AF500A911F7 /* DarkMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkMode.swift; sourceTree = ""; }; 2B1326102B2821E600301A8B /* ThisMonthAccTimeCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThisMonthAccTimeCardView.swift; sourceTree = ""; }; 2B1326122B285B1D00301A8B /* NoticeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeView.swift; sourceTree = ""; }; + 38BC7E64D66913E5A6C0834C /* Pods-24HANE.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-24HANE.debug.xcconfig"; path = "Target Support Files/Pods-24HANE/Pods-24HANE.debug.xcconfig"; sourceTree = ""; }; 5F9D5EBD040CA1B419BF545D /* Pods_24HANE.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_24HANE.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9A1A4BED299ADE650076D650 /* TodayAccTimeCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayAccTimeCardView.swift; sourceTree = ""; }; - 9AF0C045D5FEBE82760C04A3 /* Pods-24HANE.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-24HANE.debug.xcconfig"; path = "Target Support Files/Pods-24HANE/Pods-24HANE.debug.xcconfig"; sourceTree = ""; }; 9AF730EC299CC54F00AF2E53 /* DateExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateExtensions.swift; sourceTree = ""; }; 9AF730EE299D3A4900AF2E53 /* CalendarGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarGridView.swift; sourceTree = ""; }; 9AF730F0299D58F100AF2E53 /* AccTimeCardForCalendarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccTimeCardForCalendarView.swift; sourceTree = ""; }; @@ -338,8 +338,8 @@ CC7009C835DF6CA6ECA500B0 /* Pods */ = { isa = PBXGroup; children = ( - 9AF0C045D5FEBE82760C04A3 /* Pods-24HANE.debug.xcconfig */, A021B0070CB31045F069E3A2 /* Pods-24HANE.release.xcconfig */, + 38BC7E64D66913E5A6C0834C /* Pods-24HANE.debug.xcconfig */, ); path = Pods; sourceTree = ""; @@ -607,6 +607,7 @@ /* Begin XCBuildConfiguration section */ 0E165500299A285E001E5EED /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D680AC322BB17CA00083025D /* env.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -667,6 +668,7 @@ }; 0E165501299A285E001E5EED /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D680AC322BB17CA00083025D /* env.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -721,7 +723,7 @@ }; 0E165503299A285E001E5EED /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9AF0C045D5FEBE82760C04A3 /* Pods-24HANE.debug.xcconfig */; + baseConfigurationReference = 38BC7E64D66913E5A6C0834C /* Pods-24HANE.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; diff --git a/HANE24/View/MainView.swift b/HANE24/View/MainView.swift index 5c82ee6..34c0d0e 100644 --- a/HANE24/View/MainView.swift +++ b/HANE24/View/MainView.swift @@ -9,6 +9,8 @@ import SwiftUI struct MainView: View { @EnvironmentObject var hane: Hane + @EnvironmentObject var calendar: CalendarVM + @State var selection = 1 @Environment(\.colorScheme) var colorScheme @@ -37,6 +39,7 @@ struct MainView: View { .task { do { try await hane.refresh() + try await calendar.updateMonthlyLogs(date: .now) } catch { print("error on MainView \(error.localizedDescription)") } diff --git a/HANE24/ViewModel/CalendarVM.swift b/HANE24/ViewModel/CalendarVM.swift index c786acd..f86b168 100644 --- a/HANE24/ViewModel/CalendarVM.swift +++ b/HANE24/ViewModel/CalendarVM.swift @@ -32,17 +32,18 @@ class CalendarVM: ObservableObject, CalendarProtocol { // 데이터를 갱신하거나 불러오는 함수 func getPerMonth(year: Int, month: Int) async throws -> PerMonth { - var components = URLComponents(string: network.apiRoot + "/v3/tag-log/getAllTagPerMonth")! + var components = URLComponents(string: "/v3/tag-log/getAllTagPerMonth")! let year = URLQueryItem(name: "year", value: "\(year)") let month = URLQueryItem(name: "month", value: "\(month)") components.queryItems = [year, month] guard let perMonth = try await network.getRequest(components.url!.absoluteString, type: PerMonth.self) else { - fatalError() + fatalError("CalendarVM - getPerMonth") } return perMonth } + @MainActor func updateMonthlyLogs(date: Date) async throws { self.loading = true @@ -73,7 +74,6 @@ class CalendarVM: ObservableObject, CalendarProtocol { func convert(_ from: [InOutLog]) -> [Log] { guard !from.isEmpty else { return [] } - print(from) var logArray = from.map { var inTime: String? var outTime: String? @@ -93,7 +93,7 @@ class CalendarVM: ObservableObject, CalendarProtocol { logArray[0].logTime = (logArray[0].logTime == "누락" && calendarModel.selectedDate.toString("yyyy.MM.dd") == Date().toString("yyyy.MM.dd")) ? "-" : logArray[0].logTime return logArray.reversed() } - + // 초기화 init(network: NetworkProtocol = NetworkManager.shared) { self.network = network diff --git a/HANE24/ViewModel/HaneVM.swift b/HANE24/ViewModel/HaneVM.swift index 6b08f3d..075eaa7 100644 --- a/HANE24/ViewModel/HaneVM.swift +++ b/HANE24/ViewModel/HaneVM.swift @@ -232,7 +232,7 @@ extension Hane { apicall */ @MainActor - func updateMonthlyLogs(date: Date) async throws { + func updateMonthlyLogs(date: Date = .now) async throws { // update MonthlyLogs self.loading = true diff --git a/HANE24/ViewModel/NetworkManager.swift b/HANE24/ViewModel/NetworkManager.swift index 746c290..981f364 100644 --- a/HANE24/ViewModel/NetworkManager.swift +++ b/HANE24/ViewModel/NetworkManager.swift @@ -34,6 +34,7 @@ class NetworkManager: NetworkProtocol { /// FIXME: invalid URL의 경우 error handling return nil } + guard let token = UserDefaults.standard.string(forKey: "Token") else { /// FIXME: token invalid 경우에 signIn 상태 변경 throw MyError.tokenExpired("get new token!") diff --git a/Podfile.lock b/Podfile.lock index e71e163..d606c34 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -11,6 +11,6 @@ SPEC REPOS: SPEC CHECKSUMS: SwiftLint: c1de071d9d08c8aba837545f6254315bc900e211 -PODFILE CHECKSUM: 68dbe72762bbebaea8bf8e8f527b8e90a20daf32 +PODFILE CHECKSUM: 88f9b39c53325d9e15337ef2888bc9a9dde656e7 COCOAPODS: 1.14.3 From 3343fb57045d3967243f9490462366a279ab7017 Mon Sep 17 00:00:00 2001 From: HiHoi Date: Thu, 28 Mar 2024 15:57:27 +0900 Subject: [PATCH 4/6] feat: converted daily Log is add --- HANE24/View/Calendar/CalendarView.swift | 2 +- HANE24/ViewModel/CalendarVM.swift | 35 ++++++++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/HANE24/View/Calendar/CalendarView.swift b/HANE24/View/Calendar/CalendarView.swift index 8d3db57..2d4e7d1 100644 --- a/HANE24/View/Calendar/CalendarView.swift +++ b/HANE24/View/Calendar/CalendarView.swift @@ -30,7 +30,7 @@ struct CalendarView: View { totalAccTime: calendarVM.calendarModel.monthlyTotalAccumulationTime, validAccTime: calendarVM.calendarModel.monthlyAcceptedAccumulationTime) .padding(.vertical, 10) - TagLogView(logList: calendarVM.convert(calendarVM.calendarModel.monthlyLogs[calendarVM.calendarModel.selectedDate.toString("yyyy.MM.dd")] ?? [])) + TagLogView(logList: calendarVM.convertedSelectedMonthlyLog) .padding(.top, 10) Spacer() } diff --git a/HANE24/ViewModel/CalendarVM.swift b/HANE24/ViewModel/CalendarVM.swift index f86b168..58683fb 100644 --- a/HANE24/ViewModel/CalendarVM.swift +++ b/HANE24/ViewModel/CalendarVM.swift @@ -7,13 +7,24 @@ import Foundation -protocol CalendarDataProtocol {} +protocol CalendarDataProtocol { + // Calendar에서 사용할 Model + var calendarModel: CalendarModel { get set } + // 데이터를 불러올 때 loading 페이지 노출 여부 + var loading: Bool { get set } + + // + func convert(_ from: [InOutLog]) -> [Log] +} -protocol CalendarFetchProtocol {} +protocol CalendarFetchProtocol { + func updateMonthlyLogs(date: Date) async throws +} protocol CalendarProtocol {} struct CalendarModel { + // 데이터의 원본 var selectedDate: Date = .now var monthlyTotalAccumulationTime: Int64 = 0 var monthlyAcceptedAccumulationTime: Int64 = 0 @@ -25,13 +36,20 @@ class CalendarVM: ObservableObject, CalendarProtocol { // 네트워크VM 객체 private var network: NetworkProtocol - // 사용할 날짜 데이터 @Published var calendarModel: CalendarModel = CalendarModel() @Published var loading = false - // 데이터를 갱신하거나 불러오는 함수 + // 일일 로그를 보여줄 때 변환을 거친 변수 + var convertedSelectedMonthlyLog: [Log] { + let selectedDate = calendarModel.selectedDate + let monthlyLogs = calendarModel.monthlyLogs + let selectedLog = monthlyLogs[selectedDate.toString("yyyy.MM.dd")] + let converted = convert(selectedLog ?? []) + return converted + } - func getPerMonth(year: Int, month: Int) async throws -> PerMonth { + // 데이터를 갱신하거나 불러오는 함수 + private func getPerMonth(year: Int, month: Int) async throws -> PerMonth { var components = URLComponents(string: "/v3/tag-log/getAllTagPerMonth")! let year = URLQueryItem(name: "year", value: "\(year)") let month = URLQueryItem(name: "month", value: "\(month)") @@ -69,9 +87,7 @@ class CalendarVM: ObservableObject, CalendarProtocol { self.loading = false } - - // 보여줄 문자를 파싱하는 함수들 - + // 선택한 일자의 일일 기록을 보여주기 위해 변환하는 함수 func convert(_ from: [InOutLog]) -> [Log] { guard !from.isEmpty else { return [] } var logArray = from.map { @@ -90,10 +106,11 @@ class CalendarVM: ObservableObject, CalendarProtocol { } return Log(inTime: inTime, outTime: outTime, logTime: logTime) } + // 누락된 경우를 체크 + let isMissing: Bool = logArray[0].logTime == "누락" && calendarModel.selectedDate.toString("yyyy.MM.dd") == Date().toString("yyyy.MM.dd") logArray[0].logTime = (logArray[0].logTime == "누락" && calendarModel.selectedDate.toString("yyyy.MM.dd") == Date().toString("yyyy.MM.dd")) ? "-" : logArray[0].logTime return logArray.reversed() } - // 초기화 init(network: NetworkProtocol = NetworkManager.shared) { self.network = network From c7ac5544489542fcbd40e8b244511855c02f1784 Mon Sep 17 00:00:00 2001 From: HiHoi Date: Thu, 28 Mar 2024 17:21:55 +0900 Subject: [PATCH 5/6] feat: modify swiftlint - disabled line_length and update calendar test --- .swiftlint.yml | 5 +- HANE24TEST/HANE24Test.swift | 116 ++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 51 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 95b141d..c2cfc6c 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,2 +1,5 @@ identifier_name: - min_length: 0 \ No newline at end of file + min_length: 0 + +disabled_rules: + - line_length \ No newline at end of file diff --git a/HANE24TEST/HANE24Test.swift b/HANE24TEST/HANE24Test.swift index 61a5c33..34f7fae 100644 --- a/HANE24TEST/HANE24Test.swift +++ b/HANE24TEST/HANE24Test.swift @@ -52,44 +52,60 @@ let monthlyJsonData = """ } """.data(using: .utf8)! + + +let emptyMonthlyData = PerMonth(login: "hoslim", profileImage: "https://cdn.intra.42.fr/users/8f20c45abe403f1fd56b58211f819bea/hoslim.jpg", inOutLogs: [], totalAccumulationTime: 0, acceptedAccumulationTime: 0) + //let utcAnswer = [Log(inTime: Optional("03:14:39"), outTime: Optional("07:42:19"), logTime: Optional("19:27:40"))] let answer = [Log(inTime: Optional("12:14:39"), outTime: Optional("16:42:19"), logTime: Optional("04:27:40"))] /** - + 테스트해야 하는 함수 및 기능 - + # 캘린더 1. updateMonthlyLogs 테스트 2. callPerMonth 테스트 3. 누락 및 상태에 대한 테스트 - + # 테스트 구현시 원칙 1. Given 2. When 3. Then - + */ +//protocol MockNetworkInfoProtocol { +// var session: URLSession { get set } +// var apiRoot: String { get set } +//} +// +//protocol MockNetworkGetProtocol { +// func getRequest(_ urlPath: String, type: T.Type) async throws -> T? where T : Decodable +//} +// +//protocol MockNetworkProtocol: MockNetworkProtocol {} + class MockNetwork: NetworkProtocol { static var shared = MockNetwork() var session: URLSession - + var apiRoot: String = "" - + func getRequest(_ urlPath: String, type: T.Type) async throws -> T? where T : Decodable { - return nil + let decodedData = try JSONDecoder().decode(type.self, from: monthlyJsonData) + return decodedData } func postRequest(_ urlPath: String) async throws { return } - + func patchRequest(_ urlPath: String) async throws { return } - + func deleteRequest(_ urlPath: String) async throws { return } @@ -101,79 +117,79 @@ class MockNetwork: NetworkProtocol { final class HaneCalendarTest: XCTestCase { - // ViewModel - var sut: Hane! - // CalendarView 안에 있는 convert 함수를 테스트하기 위해 View 객체 생성 - var calendarVM: CalendarVM! + // CalendarVM 객체 + var sut: CalendarVM! // 테스트 객체 초기화 override func setUpWithError() throws { try super.setUpWithError() - sut = Hane() - calendarVM = CalendarVM(network: MockNetwork.shared) + sut = CalendarVM(network: MockNetwork.shared) } // 테스트 이후 객체 소멸 override func tearDownWithError() throws { - calendarVM = nil sut = nil try super.tearDownWithError() } // MARK: - Monthly Data Test - func testSeperateMonthlyData() { - // Given: Fake API call and receive data + func testGetMonthlyData() async { do { - let data = try JSONDecoder().decode(PerMonth.self, from: monthlyJsonData) - sut.perMonth = data + try await sut.updateMonthlyLogs(date: .now) } catch { - XCTFail("JSON Parsing fail") - return + XCTFail("testGetMonthlyData data load is failed") } + XCTAssertNotNil(sut.calendarModel.monthlyLogs) + } - // when - let parsedData = calendarVM.convert(sut.perMonth.inOutLogs) - // 질문사항 1. convert 함수가 왜 calendarView에 종속되어 있는지 - - // then - // 1. - XCTAssertEqual(parsedData, answer) + func testGetDailyTotalTimesInAMonth() async { + do { + try await sut.updateMonthlyLogs(date: .now) + } catch { + XCTFail("testGetDailyTotalTimesInAMonth data load is failed") + } + XCTAssertNotNil(sut.calendarModel.dailyTotalTimesInAMonth) } - func testEmptyMonthlyData() { - // given + func testMonthlyTotalAccumulationTime() async { do { - let data = try JSONDecoder().decode(PerMonth.self, from: emptyJsonData) - sut.perMonth = data + try await sut.updateMonthlyLogs(date: .now) } catch { - XCTFail("JSON Parse Fail") - return + XCTFail("testMonthlyTotalAccumulationTime data load is failed") } + XCTAssertNotNil(sut.calendarModel.monthlyTotalAccumulationTime) + } - // when - let parsedData = calendarVM.convert(sut.perMonth.inOutLogs) + func testMonthlyAcceptedAccumulationTime() async { + do { + try await sut.updateMonthlyLogs(date: .now) + } catch { + XCTFail("testMonthlyAcceptedAccumulationTime data load is failed") + } + XCTAssertNotNil(sut.calendarModel.monthlyAcceptedAccumulationTime) + } - // then - XCTAssertEqual(parsedData, []) + func testLoading() async { + do { + try await sut.updateMonthlyLogs(date: .now) + } catch { + XCTFail("testLoading data load is failed") + } + XCTAssertFalse(sut.loading) } // MARK: - Daily Data Test - func testSeperateDailyData() { - // given + func testSeperateDailyData() async { do { - let data = try JSONDecoder().decode(PerMonth.self, from: monthlyJsonData) - sut.perMonth = data + try await sut.updateMonthlyLogs(date: .now) } catch { - XCTFail("JSON Parse Fail") - return + XCTFail("testSeperateDailyData data load is failed") } - - // when - let parsedData = calendarVM.convert(sut.perMonth.inOutLogs) - let parsedDataFirst = parsedData[0] + let parsedData = sut.convertedSelectedMonthlyLog + print(parsedData) // then - XCTAssertEqual(parsedDataFirst, answer[0]) +// XCTAssertEqual(parsedData, answer[0]) } // // MARK: - Missing Data Test From 097d4b67f04fea6b564539dfb7275266416d3c34 Mon Sep 17 00:00:00 2001 From: HiHoi Date: Sun, 31 Mar 2024 22:26:12 +0900 Subject: [PATCH 6/6] feat: calendar test add --- HANE24TEST/HANE24Test.swift | 59 +++++-------------------------------- 1 file changed, 8 insertions(+), 51 deletions(-) diff --git a/HANE24TEST/HANE24Test.swift b/HANE24TEST/HANE24Test.swift index 34f7fae..6f0fe23 100644 --- a/HANE24TEST/HANE24Test.swift +++ b/HANE24TEST/HANE24Test.swift @@ -36,6 +36,9 @@ let missingJsonData = """ let missingAnswer = [Log(inTime: Optional("18:08:31"), outTime: nil, logTime: Optional("누락"))] +let emptyMonthlyData = PerMonth(login: "hoslim", profileImage: "https://cdn.intra.42.fr/users/8f20c45abe403f1fd56b58211f819bea/hoslim.jpg", inOutLogs: [], totalAccumulationTime: 0, acceptedAccumulationTime: 0) + +// 2022-12-30일자 기록 let monthlyJsonData = """ { "login": "hoslim", @@ -52,40 +55,8 @@ let monthlyJsonData = """ } """.data(using: .utf8)! - - -let emptyMonthlyData = PerMonth(login: "hoslim", profileImage: "https://cdn.intra.42.fr/users/8f20c45abe403f1fd56b58211f819bea/hoslim.jpg", inOutLogs: [], totalAccumulationTime: 0, acceptedAccumulationTime: 0) - -//let utcAnswer = [Log(inTime: Optional("03:14:39"), outTime: Optional("07:42:19"), logTime: Optional("19:27:40"))] let answer = [Log(inTime: Optional("12:14:39"), outTime: Optional("16:42:19"), logTime: Optional("04:27:40"))] -/** - - 테스트해야 하는 함수 및 기능 - - # 캘린더 - 1. updateMonthlyLogs 테스트 - 2. callPerMonth 테스트 - 3. 누락 및 상태에 대한 테스트 - - # 테스트 구현시 원칙 - 1. Given - 2. When - 3. Then - - */ - -//protocol MockNetworkInfoProtocol { -// var session: URLSession { get set } -// var apiRoot: String { get set } -//} -// -//protocol MockNetworkGetProtocol { -// func getRequest(_ urlPath: String, type: T.Type) async throws -> T? where T : Decodable -//} -// -//protocol MockNetworkProtocol: MockNetworkProtocol {} - class MockNetwork: NetworkProtocol { static var shared = MockNetwork() @@ -181,31 +152,17 @@ final class HaneCalendarTest: XCTestCase { // MARK: - Daily Data Test func testSeperateDailyData() async { do { - try await sut.updateMonthlyLogs(date: .now) + sut.calendarModel.selectedDate = Date(timeIntervalSince1970: 1672358400) + try await sut.updateMonthlyLogs(date: Date(timeIntervalSince1970: 1672358400)) } catch { XCTFail("testSeperateDailyData data load is failed") } let parsedData = sut.convertedSelectedMonthlyLog - print(parsedData) // then -// XCTAssertEqual(parsedData, answer[0]) + XCTAssertEqual(parsedData, answer) } -// // MARK: - Missing Data Test -// func testMissingDailyData() { -// // 질문사항 3. 이 부분을 테스트 하려면 convert 함수 내 hane의 selectedDate를 사용하는데 이 용도와 계산 원리 -// do { -// let data = try JSONDecoder().decode(PerMonth.self, from: missingJsonData) -// sut.perMonth = data -// } catch { -// XCTFail("JSON Parse Fail") -// return -// } -// -// calendarView.$hane.selectedDate = Date.now -// let parsedData = calendarView.convert(sut.perMonth.inOutLogs) -// -// XCTAssertEqual(parsedData, missingAnswer) -// } + // MARK: - Missing Data Test + }