diff --git a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/ChallengeSuccessInfoMapper.swift b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/ChallengeSuccessInfoMapper.swift new file mode 100644 index 00000000..d3465e83 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/ChallengeSuccessInfoMapper.swift @@ -0,0 +1,18 @@ +// +// DailyChallengeTransform.swift +// Data +// +// Created by 류희재 on 10/29/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation + +import Domain +import Networks + +extension FinishedDailyChallenge { + func toEntity() -> ChallengeSuccessInfo { + return .init(challengeDate: challengeDate, isSuccess: isSuccess) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift index abd3b747..385207e9 100644 --- a/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift +++ b/HMH_Tuist_iOS/Projects/Data/Sources/Mapper/Challenge/DailyChallengeInfoMapper.swift @@ -1,18 +1,20 @@ // -// DailyChallengeTransform.swift +// HomeChallengeDetailMapper.swift // Data // -// Created by 류희재 on 10/29/24. +// Created by 류희재 on 11/5/24. // Copyright © 2024 HMH-iOS. All rights reserved. // -import Foundation - import Domain import Networks -extension FinishedDailyChallenge { - func toEntity() -> DailyChallengeInfo { - return .init(challengeDate: challengeDate, isSuccess: isSuccess) +extension DailyChallengeResult { + public func toEntity() -> DailyChallengeInfo { + .init( + status: status, + goalTime: goalTime, + apps: apps.map { $0.toEntity() } + ) } } diff --git a/HMH_Tuist_iOS/Projects/Data/Sources/Repository/ChallengeRepository.swift b/HMH_Tuist_iOS/Projects/Data/Sources/Repository/ChallengeRepository.swift index b9900216..8eb7f2e5 100644 --- a/HMH_Tuist_iOS/Projects/Data/Sources/Repository/ChallengeRepository.swift +++ b/HMH_Tuist_iOS/Projects/Data/Sources/Repository/ChallengeRepository.swift @@ -12,60 +12,60 @@ import Combine import Domain import Networks -struct ChallengeRepository: ChallengeRepositoryType { +public struct ChallengeRepository: ChallengeRepositoryType { private let service: ChallengeServiceType - init(service: ChallengeServiceType) { + public init(service: ChallengeServiceType) { self.service = service } - func getdailyChallenge() -> AnyPublisher { - service.getdailyChallenge() + public func getdailyChallenge() -> AnyPublisher { + service.getDailyChallenge() .map { $0.toEntity() } .mapToDomainError(to: ChallengeError.self) } - func getSuccesChallenge() -> AnyPublisher<[String], ChallengeError> { + public func getSuccesChallenge() -> AnyPublisher<[String], ChallengeError> { service.getSuccesChallenge() .map { $0.statuses } .mapToDomainError(to: ChallengeError.self) } - func createChallenge(period: Int, goalTime: Int) -> AnyPublisher { + public func createChallenge(period: Int, goalTime: Int) -> AnyPublisher { let request = CreateChallengeRequest(period: period, goalTime: goalTime) return service.createChallenge(request: request) .map { _ in () } .mapToDomainError(to: ChallengeError.self) } - func getLockChallenge() -> AnyPublisher { + public func getLockChallenge() -> AnyPublisher { return service.getLockChallenge() .map { $0.isLockToday } .mapToDomainError(to: ChallengeError.self) } - func postLockChallenge() -> AnyPublisher { + public func postLockChallenge() -> AnyPublisher { return service.postLockChallenge() .map { _ in () } .mapToDomainError(to: ChallengeError.self) } - func deleteApp(appCode: String) -> AnyPublisher { + public func deleteApp(appCode: String) -> AnyPublisher { let request = DeleteAppRequest(appCode: appCode) return service.deleteApp(request: request) .map { _ in () } .mapToDomainError(to: ChallengeError.self) } - func addApp(apps: [AppInfo]) -> AnyPublisher { + public func addApp(apps: [AppInfo]) -> AnyPublisher { let request = AddAppRequest(apps: apps.map { $0.toDTO() }) return service.addApp(request: request) .map { _ in () } .mapToDomainError(to: ChallengeError.self) } - func getChallenge() -> AnyPublisher { + public func getChallenge() -> AnyPublisher { service.getChallenge() .map { $0.toEntity() } .mapToDomainError(to: ChallengeError.self) diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/AddAppTest/AddAppTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/AddAppTest/AddAppTest.swift new file mode 100644 index 00000000..960f2b29 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/AddAppTest/AddAppTest.swift @@ -0,0 +1,58 @@ +// +// AddAppTest.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain + +/// 스크린타임 설정할 앱 추가 API 데이터 변환 테스트 +extension ChallegeRepositoryTests { + func test_스크린타임설정할앱추가_정상적인변환() { + + let expectation = XCTestExpectation(description: "스크린타임 설정할 앱 추가 API 관련 레포지토리 변환이 정상적으로 성공했습니다!") + + sut.addApp(apps: [.stub]) + .sink(receiveCompletion: { completion in + if case .failure(let error) = completion { + XCTFail("스크린타임 설정할 앱 추가 API 변환 중 실패했습니다: 에러 \(error)") + } + expectation.fulfill() + }, receiveValue: { _ in + expectation.fulfill() + }) + .store(in: cancelBag) + + wait(for: [expectation], timeout: 1.0) + } + + func test_스크린타임설정할앱추가_네트워크에러발생시_에러반환() { + + let testCases = HMHNetworkError.mockNetworkError + let expectation = XCTestExpectation(description: "에러 발생 시 네트워크 에러 반환") + + for expected in testCases { + mockService.addAppResult = Fail(error: expected).eraseToAnyPublisher() + + sut.addApp(apps: [.stub]) + .sink( + receiveCompletion: handleCompletion( + expectedError: .networkError, + expectation: expectation + ), + receiveValue: failureExpectedValueHandler() + ) + .store(in: cancelBag) + + } + + wait(for: [expectation], timeout: 1.0) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/Base/ChallegeRepositoryTests.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/Base/ChallegeRepositoryTests.swift new file mode 100644 index 00000000..c0ab08cb --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/Base/ChallegeRepositoryTests.swift @@ -0,0 +1,59 @@ +// +// ChallegeRepositoryTests.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain +import Data + +final class ChallegeRepositoryTests: XCTestCase { + + var sut: ChallengeRepositoryType! + var mockService: MockChallengeService! + var cancelBag: CancelBag! + + override func setUpWithError() throws { + cancelBag = CancelBag() + mockService = MockChallengeService() + sut = ChallengeRepository(service: mockService) + } + + override func tearDown() { + cancelBag = nil + mockService = nil + sut = nil + } +} + +extension ChallegeRepositoryTests { + public func handleCompletion(expectedError: T? = nil, expectation: XCTestExpectation) -> (Subscribers.Completion) -> Void { + return { completion in + if case .failure(let error) = completion { + XCTAssertEqual(error, expectedError, "Expected error \(String(describing: expectedError)), but got \(error)") + expectation.fulfill() + } else { + XCTFail("Expected failure with error \(String(describing: expectedError)), but received success") + } + } + } + + public func valueHandler(expectation: XCTestExpectation, expectedValue: T) -> (T) -> Void { + return { receivedValue in + XCTAssertEqual(receivedValue, expectedValue, "Received value \(receivedValue) does not match expected data \(expectedValue)") + expectation.fulfill() + } + } + + public func failureExpectedValueHandler() -> (T) -> Void { + return { _ in XCTFail("Expected failure, but got success") } + } +} + diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/Base/MockChallengeService.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/Base/MockChallengeService.swift new file mode 100644 index 00000000..d29c6823 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/Base/MockChallengeService.swift @@ -0,0 +1,61 @@ +// +// MockChallengeService.swift +// Data +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation +import Combine + +import Domain +import Networks + +final public class MockChallengeService: ChallengeServiceType { + + public init() {} + + public var getDailyChallengeResult:AnyPublisher! + public var getSuccesChallengeResult:AnyPublisher! + public var createChallengeResult:AnyPublisher! + public var getLockChallengeResult:AnyPublisher! + public var postLockChallengeResult:AnyPublisher! + public var deleteAppResult:AnyPublisher! + public var addAppResult:AnyPublisher! + public var getChallengeResult:AnyPublisher! + + + public func getDailyChallenge() -> AnyPublisher { + return getDailyChallengeResult + } + + public func getSuccesChallenge() -> AnyPublisher { + return getSuccesChallengeResult + } + + public func createChallenge(request: CreateChallengeRequest) -> AnyPublisher { + return createChallengeResult + } + + public func getLockChallenge() -> AnyPublisher { + return getLockChallengeResult + } + + public func postLockChallenge() -> AnyPublisher { + return postLockChallengeResult + } + + public func deleteApp(request: DeleteAppRequest) -> AnyPublisher { + return deleteAppResult + } + + public func addApp(request: AddAppRequest) -> AnyPublisher { + return addAppResult + } + + public func getChallenge() -> AnyPublisher { + return getChallengeResult + } +} + diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/CreateChallengeTest/CreateChallengeTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/CreateChallengeTest/CreateChallengeTest.swift new file mode 100644 index 00000000..91376c1e --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/CreateChallengeTest/CreateChallengeTest.swift @@ -0,0 +1,57 @@ +// +// CreateChallengeTest.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain + +/// 챌린지 생성 API 데이터 변환 테스트 +extension ChallegeRepositoryTests { + func test_챌린지생성_정상적인변환() { + + let expectation = XCTestExpectation(description: "챌린지 생성 API 관련 레포지토리 변환이 정상적으로 성공했습니다!") + + sut.createChallenge(period: 7, goalTime: 200000) + .sink(receiveCompletion: { completion in + if case .failure(let error) = completion { + XCTFail("챌린지 생성 API 변환 중 실패했습니다: 에러 \(error)") + } + expectation.fulfill() + }, receiveValue: { _ in + expectation.fulfill() + }) + .store(in: cancelBag) + + wait(for: [expectation], timeout: 1.0) + } + + func test_챌린지생성_네트워크에러발생시_에러반환() { + + let testCases = HMHNetworkError.mockNetworkError + let expectation = XCTestExpectation(description: "에러 발생 시 네트워크 에러 반환") + + for expected in testCases { + mockService.createChallengeResult = Fail(error: expected).eraseToAnyPublisher() + + sut.createChallenge(period: 7, goalTime: 200000) + .sink( + receiveCompletion: handleCompletion( + expectedError: .networkError, + expectation: expectation + ), + receiveValue: failureExpectedValueHandler() + ) + .store(in: cancelBag) + + } + wait(for: [expectation], timeout: 1.0) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/DeleteAppTest/DeleteAppTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/DeleteAppTest/DeleteAppTest.swift new file mode 100644 index 00000000..f04406c5 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/DeleteAppTest/DeleteAppTest.swift @@ -0,0 +1,57 @@ +// +// DeleteAppTest.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain + +/// 스크린타임 설정한 앱 삭제 API 데이터 변환 테스트 +extension ChallegeRepositoryTests { + func test_스크린타임설정한앱삭제_정상적인변환() { + + let expectation = XCTestExpectation(description: "스크린타임 설정한 앱 삭제 API 관련 레포지토리 변환이 정상적으로 성공했습니다!") + + sut.deleteApp(appCode: "10000") + .sink(receiveCompletion: { completion in + if case .failure(let error) = completion { + XCTFail("스크린타임 설정한 앱 삭제 API 변환 중 실패했습니다: 에러 \(error)") + } + expectation.fulfill() + }, receiveValue: { _ in + expectation.fulfill() + }) + .store(in: cancelBag) + + wait(for: [expectation], timeout: 1.0) + } + + func test_스크린타임설정한앱삭제_네트워크에러발생시_에러반환() { + + let testCases = HMHNetworkError.mockNetworkError + let expectation = XCTestExpectation(description: "에러 발생 시 네트워크 에러 반환") + + for expected in testCases { + mockService.deleteAppResult = Fail(error: expected).eraseToAnyPublisher() + + sut.deleteApp(appCode: "100000") + .sink( + receiveCompletion: handleCompletion( + expectedError: .networkError, + expectation: expectation + ), + receiveValue: failureExpectedValueHandler() + ) + .store(in: cancelBag) + + } + wait(for: [expectation], timeout: 1.0) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetChallengeTest/GetChallengeMockData.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetChallengeTest/GetChallengeMockData.swift new file mode 100644 index 00000000..a14b3668 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetChallengeTest/GetChallengeMockData.swift @@ -0,0 +1,77 @@ +// +// GetChallengeMockData.swift +// Data +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation + +import Networks +import Domain + +extension ChallengeDetail { + static public var expectedData: ChallengeDetail { + .init( + statuses: [ + "UNEARNED", + "UNEARNED", + "NONE", + "NONE", + "NONE", + "NONE", + "NONE" + ], + todayIndex: 2, + startDate: "2024-05-17", + challengeInfo: ChallengeInfo( + period: 7, + goalTime: 7200000, + apps: [ + .init(appCode: "#292043", goalTime: 12312420), + .init(appCode: "#693043", goalTime: 12312420) + ] + ) + ) + } +} + +extension GetChallengeResult { + static public var resultData: GetChallengeResult { + return .init( + period: 7, + statuses: [ + "UNEARNED", + "UNEARNED", + "NONE", + "NONE", + "NONE", + "NONE", + "NONE" + ], + todayIndex: 2, + startDate: "2024-05-17", + goalTime: 7200000, + apps: [ + .init(appCode: "#292043", goalTime: 12312420), + .init(appCode: "#693043", goalTime: 12312420) + ] + ) + } +} + + + + + + + + + + + + + + + diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetChallengeTest/GetChallengeTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetChallengeTest/GetChallengeTest.swift new file mode 100644 index 00000000..7a851bf6 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetChallengeTest/GetChallengeTest.swift @@ -0,0 +1,62 @@ +// +// GetChallengeTest.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain + +/// 달성현황 정보 불러오기 API 데이터 변환 테스트 +extension ChallegeRepositoryTests { + func test_달성현황정보불러오기_정상적인변환() { + let expectedData = ChallengeDetail.expectedData + let resultData = GetChallengeResult.resultData + let expectation = XCTestExpectation(description: "달성현황 정보 불러오기 관련 레포지토리 변환이 정상적으로 성공했습니다!") + + + mockService.getChallengeResult = Just(resultData) + .setFailureType(to: HMHNetworkError.self) + .eraseToAnyPublisher() + + sut.getChallenge() + .sink(receiveCompletion: { completion in + if case .failure(let error) = completion { + XCTFail("달성현황 정보 불러오기 API 변환 중 실패했습니다: 에러 \(error)") + } + }, receiveValue: valueHandler(expectation: expectation, expectedValue: expectedData)) + .store(in: cancelBag) + + + wait(for: [expectation], timeout: 1.0) + } + + func test_달성현황정보불러오기_네트워크에러발생시_에러반환() { + + let testCases = HMHNetworkError.mockNetworkError + let expectation = XCTestExpectation(description: "에러 발생 시 네트워크 에러 반환") + + for expected in testCases { + mockService.getChallengeResult = Fail(error: expected).eraseToAnyPublisher() + + sut.getChallenge() + .sink( + receiveCompletion: handleCompletion( + expectedError: .networkError, + expectation: expectation + ), + receiveValue: failureExpectedValueHandler() + ) + .store(in: cancelBag) + + } + + wait(for: [expectation], timeout: 1.0) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetDailyChallengeTest/ChallegeRepositoryTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetDailyChallengeTest/ChallegeRepositoryTest.swift new file mode 100644 index 00000000..20ab2344 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetDailyChallengeTest/ChallegeRepositoryTest.swift @@ -0,0 +1,62 @@ +// +// ChallegeRepositoryTest.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain + +/// 홈 이용시간 통계 불러오기 API 데이터 변환 테스트 +extension ChallegeRepositoryTests { + func test_홈이용시간통계불러오기_정상적인변환() { + let expectedData = DailyChallengeInfo.expectedData + let resultData = DailyChallengeResult.resultData + let expectation = XCTestExpectation(description: "홈 이용시간 통계 불러오기 관련 레포지토리 변환이 정상적으로 성공했습니다!") + + + mockService.getDailyChallengeResult = Just(resultData) + .setFailureType(to: HMHNetworkError.self) + .eraseToAnyPublisher() + + sut.getdailyChallenge() + .sink(receiveCompletion: { completion in + if case .failure(let error) = completion { + XCTFail("홈 이용시간 통계 불러오기 API 변환 중 실패했습니다: 에러 \(error)") + } + }, receiveValue: valueHandler(expectation: expectation, expectedValue: expectedData)) + .store(in: cancelBag) + + + wait(for: [expectation], timeout: 1.0) + } + + func test_홈이용시간통계불러오기_네트워크에러발생시_에러반환() { + + let testCases = HMHNetworkError.mockNetworkError + let expectation = XCTestExpectation(description: "에러 발생 시 네트워크 에러 반환") + + for expected in testCases { + mockService.getDailyChallengeResult = Fail(error: expected).eraseToAnyPublisher() + + sut.getdailyChallenge() + .sink( + receiveCompletion: handleCompletion( + expectedError: .networkError, + expectation: expectation + ), + receiveValue: failureExpectedValueHandler() + ) + .store(in: cancelBag) + + } + + wait(for: [expectation], timeout: 1.0) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetDailyChallengeTest/GetDailyChallengeMockData.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetDailyChallengeTest/GetDailyChallengeMockData.swift new file mode 100644 index 00000000..77975970 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetDailyChallengeTest/GetDailyChallengeMockData.swift @@ -0,0 +1,32 @@ +// +// GetDailyChallengeMockData.swift +// Data +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation + +import Domain +import Networks + +extension DailyChallengeInfo { + static public var expectedData: DailyChallengeInfo { + return .init( + status: "NONE", + goalTime: 7200000, + apps: [.init(appCode: "#292043", goalTime: 3200000)] + ) + } +} + +extension DailyChallengeResult { + static public var resultData: DailyChallengeResult { + return .init( + status: "NONE", + goalTime: 7200000, + apps: [.init(appCode: "#292043", goalTime: 3200000)] + ) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetSuccesChallengeTest/GetSuccesChallengeMockData.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetSuccesChallengeTest/GetSuccesChallengeMockData.swift new file mode 100644 index 00000000..2f974f6e --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetSuccesChallengeTest/GetSuccesChallengeMockData.swift @@ -0,0 +1,38 @@ +// +// GetSuccesChallengeMockData.swift +// Data +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation + +import Domain +import Networks + +extension ChallengeSuccessResult { + static public var expectedData: [[String]] { + return [ + ["안녕", "안녕", "안녕", "안녕", "안녕", "안녕"], + ["","","","",""], + ["asdfasdfasdfasdf","asdfasdfasdfasdf","asdfasdfasdfasdf"] + ] + + } +} + +extension ChallengeSuccessResult { + static public var resultData: [ChallengeSuccessResult] { + return [ + .init(statuses: ["안녕", "안녕", "안녕", "안녕", "안녕", "안녕"]), + .init(statuses: ["","","","",""]), + .init(statuses: ["asdfasdfasdfasdf","asdfasdfasdfasdf","asdfasdfasdfasdf"]) + ] + + + + } +} + + diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetSuccesChallengeTest/GetSuccesChallengeTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetSuccesChallengeTest/GetSuccesChallengeTest.swift new file mode 100644 index 00000000..840ce00f --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/GetSuccesChallengeTest/GetSuccesChallengeTest.swift @@ -0,0 +1,62 @@ +// +// GetSuccesChallengeTest.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain + +/// 챌린지 성공 여부 리스트 전송 API 데이터 변환 테스트 +extension ChallegeRepositoryTests { + func test_챌린지성공여부리스트전송_정상적인변환() { + let testCases = Array(zip(ChallengeSuccessResult.expectedData, ChallengeSuccessResult.resultData)) + let expectation = XCTestExpectation(description: "챌린지 성공 여부 리스트 전송 관련 레포지토리 변환이 정상적으로 성공했습니다!") + expectation.expectedFulfillmentCount = testCases.count + + for (expectedData, resultData) in testCases { + mockService.getSuccesChallengeResult = Just(resultData) + .setFailureType(to: HMHNetworkError.self) + .eraseToAnyPublisher() + + sut.getSuccesChallenge() + .sink(receiveCompletion: { completion in + if case .failure(let error) = completion { + XCTFail("챌린지 성공 여부 리스트 전송 API 변환 중 실패했습니다: 에러 \(error)") + } + }, receiveValue: valueHandler(expectation: expectation, expectedValue: expectedData)) + .store(in: cancelBag) + } + + wait(for: [expectation], timeout: 1.0 * Double(testCases.count)) + } + + func test_챌린지성공여부리스트전송_네트워크에러발생시_에러반환() { + + let testCases = HMHNetworkError.mockNetworkError + let expectation = XCTestExpectation(description: "에러 발생 시 네트워크 에러 반환") + + for expected in testCases { + mockService.getSuccesChallengeResult = Fail(error: expected).eraseToAnyPublisher() + + sut.getSuccesChallenge() + .sink( + receiveCompletion: handleCompletion( + expectedError: .networkError, + expectation: expectation + ), + receiveValue: failureExpectedValueHandler() + ) + .store(in: cancelBag) + + } + + wait(for: [expectation], timeout: 1.0) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/PostLockChallengeTest/PostLockChallgeTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/PostLockChallengeTest/PostLockChallgeTest.swift new file mode 100644 index 00000000..2f34f55e --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/ChallengeRepositoryTests/PostLockChallengeTest/PostLockChallgeTest.swift @@ -0,0 +1,57 @@ +// +// postLockChallgeTest.swift +// DataTests +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import XCTest +import Combine + +import Networks +import Core +import Domain + +/// 당일 잠금 여부 전송 API 데이터 변환 테스트 +extension ChallegeRepositoryTests { + func test_당일잠금여부전송_정상적인변환() { + + let expectation = XCTestExpectation(description: "당일 잠금 여부 전송 API 관련 레포지토리 변환이 정상적으로 성공했습니다!") + + sut.postLockChallenge() + .sink(receiveCompletion: { completion in + if case .failure(let error) = completion { + XCTFail("당일 잠금 여부 전송 API 변환 중 실패했습니다: 에러 \(error)") + } + expectation.fulfill() + }, receiveValue: { _ in + expectation.fulfill() + }) + .store(in: cancelBag) + + wait(for: [expectation], timeout: 1.0) + } + + func test_당일잠금여부전송_네트워크에러발생시_에러반환() { + + let testCases = HMHNetworkError.mockNetworkError + let expectation = XCTestExpectation(description: "에러 발생 시 네트워크 에러 반환") + + for expected in testCases { + mockService.postLockChallengeResult = Fail(error: expected).eraseToAnyPublisher() + + sut.postLockChallenge() + .sink( + receiveCompletion: handleCompletion( + expectedError: .networkError, + expectation: expectation + ), + receiveValue: failureExpectedValueHandler() + ) + .store(in: cancelBag) + + } + wait(for: [expectation], timeout: 1.0) + } +} diff --git a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/PointRepositoryTests/GetEarnPointTest/GetEarnPointTest.swift b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/PointRepositoryTests/GetEarnPointTest/GetEarnPointTest.swift index 40801a0a..3d4ea176 100644 --- a/HMH_Tuist_iOS/Projects/Data/Tests/Sources/PointRepositoryTests/GetEarnPointTest/GetEarnPointTest.swift +++ b/HMH_Tuist_iOS/Projects/Data/Tests/Sources/PointRepositoryTests/GetEarnPointTest/GetEarnPointTest.swift @@ -84,9 +84,3 @@ extension PointRepositoryTest { wait(for: [expectation], timeout: 1.0) } } - - - - - - diff --git a/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/AppInfo.swift b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/AppInfo.swift index 6c006738..652cf5fd 100644 --- a/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/AppInfo.swift +++ b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/AppInfo.swift @@ -6,7 +6,7 @@ // Copyright © 2024 HMH-iOS. All rights reserved. // -public struct AppInfo { +public struct AppInfo: Equatable { public let appCode: String public let goalTime: Int @@ -16,4 +16,12 @@ public struct AppInfo { } } +public extension AppInfo { + static var stub: Self { + .init( + appCode: "100000", + goalTime: 10000 + ) + } +} diff --git a/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/ChallengeDetail.swift b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/ChallengeDetail.swift index 3ad0e4ea..150b8fe1 100644 --- a/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/ChallengeDetail.swift +++ b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/ChallengeDetail.swift @@ -8,7 +8,13 @@ import Foundation -public struct ChallengeDetail { +@frozen public enum ChallengeStatus: String { + case EARNED + case FAILURE + case UNEARNED +} + +public struct ChallengeDetail: Equatable { let statuses: [String] let todayIndex: Int let startDate: String @@ -22,7 +28,7 @@ public struct ChallengeDetail { } } -public struct ChallengeInfo { +public struct ChallengeInfo: Equatable { public let period: Int public let goalTime: Int public let apps: [AppInfo] diff --git a/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/DailyChallengeInfo.swift b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/ChallengeSuccessInfo.swift similarity index 90% rename from HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/DailyChallengeInfo.swift rename to HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/ChallengeSuccessInfo.swift index 29b174c4..2ac21853 100644 --- a/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/DailyChallengeInfo.swift +++ b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/ChallengeSuccessInfo.swift @@ -6,7 +6,7 @@ // Copyright © 2024 HMH-iOS. All rights reserved. // -public struct DailyChallengeInfo { +public struct ChallengeSuccessInfo { let challengeDate: String let isSuccess: Bool diff --git a/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/HomeChallengeDetail.swift b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/HomeChallengeDetail.swift new file mode 100644 index 00000000..e793d929 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Domain/Sources/Entity/Challenge/HomeChallengeDetail.swift @@ -0,0 +1,19 @@ +// +// HomeChallengeDetail.swift +// Domain +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +public struct DailyChallengeInfo: Equatable { + public let status: String + public let goalTime: Int + public let apps: [AppInfo] + + public init(status: String, goalTime: Int, apps: [AppInfo]) { + self.status = status + self.goalTime = goalTime + self.apps = apps + } +} diff --git a/HMH_Tuist_iOS/Projects/Domain/Sources/Error/Type/ChallengeError.swift b/HMH_Tuist_iOS/Projects/Domain/Sources/Error/Type/ChallengeError.swift index 265fe9c6..9b08709e 100644 --- a/HMH_Tuist_iOS/Projects/Domain/Sources/Error/Type/ChallengeError.swift +++ b/HMH_Tuist_iOS/Projects/Domain/Sources/Error/Type/ChallengeError.swift @@ -12,7 +12,7 @@ public enum ChallengeError: DomainError { case invalidChallengePeriod case goalTimeIsNil case invalidGoalTime - case unknown + case networkError public static func error(with message: String) -> ChallengeError { switch message { @@ -27,7 +27,7 @@ public enum ChallengeError: DomainError { case "유효한 숫자의 목표 시간을 입력해주세요.": return .invalidGoalTime default: - return .unknown + return .networkError } } } diff --git a/HMH_Tuist_iOS/Projects/Domain/Sources/RepositoryInterface/ChallengeRepositoryType.swift b/HMH_Tuist_iOS/Projects/Domain/Sources/RepositoryInterface/ChallengeRepositoryType.swift index cdce74c8..cebc2a46 100644 --- a/HMH_Tuist_iOS/Projects/Domain/Sources/RepositoryInterface/ChallengeRepositoryType.swift +++ b/HMH_Tuist_iOS/Projects/Domain/Sources/RepositoryInterface/ChallengeRepositoryType.swift @@ -10,7 +10,7 @@ import Foundation import Combine public protocol ChallengeRepositoryType { - func getdailyChallenge() -> AnyPublisher + func getdailyChallenge() -> AnyPublisher func getSuccesChallenge() -> AnyPublisher<[String], ChallengeError> func createChallenge(period: Int, goalTime: Int) -> AnyPublisher func getLockChallenge() -> AnyPublisher diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/ChallengeSuccessDTO.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/ChallengeSuccessDTO.swift index 5fd9b7c9..b7feabfc 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/ChallengeSuccessDTO.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/ChallengeSuccessDTO.swift @@ -18,6 +18,10 @@ public struct FinishedDailyChallenge: Encodable { public struct ChallengeSuccessResult: Decodable { public let statuses: [String] + + public init(statuses: [String]) { + self.statuses = statuses + } } public extension ChallengeSuccessResult { diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/DailyChallegeDTO.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/DailyChallegeDTO.swift new file mode 100644 index 00000000..09e30265 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/DailyChallegeDTO.swift @@ -0,0 +1,31 @@ +// +// DailyChallegeDTO.swift +// Networks +// +// Created by 류희재 on 11/5/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Foundation + +public struct DailyChallengeResult: Decodable { + public let status: String + public let goalTime: Int + public let apps: [AppInfoDTO] + + public init(status: String, goalTime: Int, apps: [AppInfoDTO]) { + self.status = status + self.goalTime = goalTime + self.apps = apps + } +} + +public extension DailyChallengeResult { + static var stub1: Self { + .init( + status: "1234", + goalTime: 123434, + apps: [.stub]) + } +} + diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/GetChallengeDTO.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/GetChallengeDTO.swift index 861dc9b6..a6d9227d 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/GetChallengeDTO.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/DTO/Challenge/GetChallengeDTO.swift @@ -8,6 +8,14 @@ import Foundation public struct GetChallengeResult: Decodable { + public init(period: Int, statuses: [String], todayIndex: Int, startDate: String, goalTime: Int, apps: [AppInfoDTO]) { + self.period = period + self.statuses = statuses + self.todayIndex = todayIndex + self.startDate = startDate + self.goalTime = goalTime + self.apps = apps + } public let period: Int public let statuses: [String] public let todayIndex: Int diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Service/Challenge/ChallengeService.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Service/Challenge/ChallengeService.swift index 5afc46de..f19d0feb 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Service/Challenge/ChallengeService.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Sources/Service/Challenge/ChallengeService.swift @@ -12,7 +12,7 @@ import Combine public typealias ChallengeService = BaseService public protocol ChallengeServiceType { - func getdailyChallenge() -> AnyPublisher + func getDailyChallenge() -> AnyPublisher func getSuccesChallenge() -> AnyPublisher func createChallenge(request: CreateChallengeRequest) -> AnyPublisher func getLockChallenge() -> AnyPublisher @@ -23,7 +23,7 @@ public protocol ChallengeServiceType { } extension ChallengeService: ChallengeServiceType { - public func getdailyChallenge() -> AnyPublisher { + public func getDailyChallenge() -> AnyPublisher { return requestWithResult(.getdailyChallenge) } @@ -57,7 +57,7 @@ extension ChallengeService: ChallengeServiceType { } struct StubChallengeService: ChallengeServiceType { - func getdailyChallenge() -> AnyPublisher { + func getDailyChallenge() -> AnyPublisher { return Just(.stub1) .setFailureType(to: HMHNetworkError.self) .eraseToAnyPublisher() diff --git a/HMH_Tuist_iOS/Projects/Modules/Networks/Tests/Sources/Service/ChallengeServiceTests.swift b/HMH_Tuist_iOS/Projects/Modules/Networks/Tests/Sources/Service/ChallengeServiceTests.swift index 65b0873a..58fcf4d6 100644 --- a/HMH_Tuist_iOS/Projects/Modules/Networks/Tests/Sources/Service/ChallengeServiceTests.swift +++ b/HMH_Tuist_iOS/Projects/Modules/Networks/Tests/Sources/Service/ChallengeServiceTests.swift @@ -37,7 +37,7 @@ final class ChallengeServiceTests: XCTestCase { let expectation = XCTestExpectation() - sut.getdailyChallenge() + sut.getDailyChallenge() .sink { completion in if case let .failure(err) = completion { XCTFail(err.localizedDescription)} } receiveValue: { roomDetails in