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

πŸ”€ :: [#101] μ•ˆλ§ˆμ˜μž Feature κ΅¬ν˜„ #117

Merged
merged 24 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bdf171c
:recycle: :: [#101] DesignSystem / μ‹ μ²­ν•œ ν•™μƒμ˜ CardView μž¬μ‚¬μš©μ„± μ£ΌκΈ°
baekteun Jul 26, 2023
8947f94
:lipstick: :: [#101] MassageFeature / Massage UI
baekteun Jul 26, 2023
8b4c752
:sparkles: :: [#101] MassageFeature / Demo μΆ”κ°€
baekteun Jul 26, 2023
47fe397
:pencil2: :: [#101] MassageFeature / NoticeFeatureDemo -> MassageFeat…
baekteun Jul 26, 2023
7db3ef1
:truck: :: [#101] BaseDomainInterface / SelfStudyDomainInterface Gend…
baekteun Jul 26, 2023
3d591c2
:sparkles: :: [#101] MassageDomain / FetchMassageRankListUseCase Inte…
baekteun Jul 26, 2023
0350d1a
:sparkles: :: [#101] MassageDomain / FetchMassageRankListUseCase Impl…
baekteun Jul 26, 2023
ad2deb6
:sparkles: :: [#101] MassageDomain / FetchMassageRankListUseCase Spy
baekteun Jul 26, 2023
71982cd
:white_check_mark: :: [#101] MassageDomain / FetchMassageRankListUseC…
baekteun Jul 26, 2023
b9059b3
:sparkles: :: [#101] MassageFeature / FetchMassageRankListUseCase DI
baekteun Jul 26, 2023
a524eb4
:sparkles: :: [#101] MassageFeature / MassageStore massageRank 정보 fet…
baekteun Jul 26, 2023
d1d1672
:sparkles: :: [#101] MassageFeature / MassageStore LoadCurrentUserRol…
baekteun Jul 26, 2023
26c7238
:sparkles: :: [#101] MassageFeature / MassageStore - viewDidLoad action
baekteun Jul 26, 2023
bb7a7b0
:sparkles: :: [#101] MassageFeature / MassageCell Databinding adapt
baekteun Jul 26, 2023
00a3dab
:sparkles: :: [#101] MassageFeature / MassageViewController, MassageS…
baekteun Jul 26, 2023
25c300b
:sparkles: :: [#101] MassageFeature / Massageμ‹ μ²­ν•œ μ‚¬λžŒμ΄ 없을 λ•Œ UI 및 Binding
baekteun Jul 26, 2023
8d2e3d8
:dizzy: :: [#101] NoticeFeature / 첫번째둜 곡지듀을 κ°€μ Έμ˜¬λ•ŒλŠ” refreshκ°€ λ™μž‘ν•˜μ§€ μ•Šλ„λ‘
baekteun Jul 26, 2023
cbecb6e
:sparkles: :: [#101] SelfStudyFeature / 첫번째둜 μžμŠ΅μ‹ μ²­ν•œ μ‚¬λžŒλ“€μ„ κ°€μ Έμ˜¬λ•ŒλŠ” Refresh…
baekteun Jul 26, 2023
ea0ee86
:white_check_mark: :: [#101] MassageFeature / ν•΄λ‹Ή μƒνƒœλ§Œ sinkν•˜λ„λ‘ λ³€κ²½
baekteun Jul 26, 2023
0c4489a
:heavy_plus_sign: :: [#101] SelfStudyDomain / BaseDomainInterface -> …
baekteun Jul 26, 2023
6461351
Merge branch 'master' of https://github.com/Team-Ampersand/Dotori-iOS…
baekteun Jul 26, 2023
f44ecde
:heavy_plus_sign: :: [#101] MassageDomain / BaseDomainInterface -> Ma…
baekteun Jul 26, 2023
46fe4d2
:truck: :: [#101] SelfStudyFeature / dotoriNavigationBarLabel -> self…
baekteun Jul 26, 2023
5eb3ce4
:pencil2: :: [#101] SelfStudyFeature / λ³€μˆ˜λͺ… μˆ˜μ • 반영 μ•ˆν•œκ²ƒ μˆ˜μ •
baekteun Jul 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
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ public protocol RemoteMassageDataSource {
func fetchMassageInfo() async throws -> MassageInfoEntity
func applyMassage() async throws
func cancelMassage() async throws
func fetchMassageRankList() async throws -> [MassageRankEntity]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import BaseDomainInterface
import Foundation

public struct MassageRankEntity: Equatable {
public let id: Int
public let rank: Int
public let stuNum: String
public let memberName: String
public let gender: GenderType

public init(id: Int, rank: Int, stuNum: String, memberName: String, gender: GenderType) {
self.id = id
self.rank = rank
self.stuNum = stuNum
self.memberName = memberName
self.gender = gender
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public typealias MassageRankModel = MassageRankEntity
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ public protocol MassageRepository {
func fetchMassageInfo() async throws -> MassageInfoEntity
func applyMassage() async throws
func cancelMassage() async throws
func fetchMassageRankList() async throws -> [MassageRankEntity]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public protocol FetchMassageRankListUseCase {
func callAsFunction() async throws -> [MassageRankModel]
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@ public final class MassageDomainAssembly: Assembly {
container.register(CancelMassageUseCase.self) { resolver in
CancelMassageUseCaseImpl(massageRepository: resolver.resolve(MassageRepository.self)!)
}

container.register(FetchMassageRankListUseCase.self) { resolver in
FetchMassageRankListUseCaseImpl(massageRepository: resolver.resolve(MassageRepository.self)!)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import BaseDomainInterface
import MassageDomainInterface
import Foundation

struct FetchMassageRankListResponseDTO: Decodable {
let list: [MassageRankResponseDTO]

struct MassageRankResponseDTO: Decodable {
let id: Int
let rank: Int
let stuNum: String
let memberName: String
let gender: GenderType
}
}

extension FetchMassageRankListResponseDTO {
func toDomain() -> [MassageRankEntity] {
self.list
.map { $0.toDomain() }
}
}

extension FetchMassageRankListResponseDTO.MassageRankResponseDTO {
func toDomain() -> MassageRankEntity {
MassageRankEntity(id: id, rank: rank, stuNum: stuNum, memberName: memberName, gender: gender)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public enum MassageEndpoint {
case fetchMassageInfo
case applyMassage
case cancelMassage
case fetchMassageRankList
}

extension MassageEndpoint: DotoriEndpoint {
Expand All @@ -24,6 +25,9 @@ extension MassageEndpoint: DotoriEndpoint {

case .cancelMassage:
return .delete("")

case .fetchMassageRankList:
return .get("/rank")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ final class RemoteMassageDataSourceImpl: RemoteMassageDataSource {
func cancelMassage() async throws {
try await networking.request(MassageEndpoint.cancelMassage)
}

func fetchMassageRankList() async throws -> [MassageRankEntity] {
try await networking.request(
MassageEndpoint.fetchMassageRankList,
dto: FetchMassageRankListResponseDTO.self
)
.toDomain()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ final class MassageRepositoryImpl: MassageRepository {
func cancelMassage() async throws {
try await remoteMassageDataSource.cancelMassage()
}

func fetchMassageRankList() async throws -> [MassageRankEntity] {
try await remoteMassageDataSource.fetchMassageRankList()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import MassageDomainInterface

struct FetchMassageRankListUseCaseImpl: FetchMassageRankListUseCase {
private let massageRepository: any MassageRepository

init(massageRepository: any MassageRepository) {
self.massageRepository = massageRepository
}

func callAsFunction() async throws -> [MassageRankModel] {
try await massageRepository.fetchMassageRankList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ final class RemoteMassageDataSourceSpy: RemoteMassageDataSource {
func cancelMassage() async throws {
cancelMassageCallCount += 1
}

var fetchMassageRankListCallCount = 0
var fetchMassageRankListHandler: () async throws -> [MassageRankEntity] = { [] }
func fetchMassageRankList() async throws -> [MassageRankEntity] {
fetchMassageRankListCallCount += 1
return try await fetchMassageRankListHandler()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ final class MassageRepositorySpy: MassageRepository {
func cancelMassage() async throws {
cancelMassageCallCount += 1
}

var fetchMassageRankListCallCount = 0
var fetchMassageRankListHandler: () async throws -> [MassageRankEntity] = { [] }
func fetchMassageRankList() async throws -> [MassageRankEntity] {
fetchMassageRankListCallCount += 1
return try await fetchMassageRankListHandler()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import MassageDomainInterface

final class FetchMassageRankListUseCaseSpy: FetchMassageRankListUseCase {
var fetchMassageRankListCallCount = 0
var fetchMassageRankListHandler: () async throws -> [MassageRankEntity] = { [] }
func callAsFunction() async throws -> [MassageRankModel] {
fetchMassageRankListCallCount += 1
return try await fetchMassageRankListHandler()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import MassageDomainInterface
import XCTest
@testable import MassageDomain
@testable import MassageDomainTesting

final class FetchMassageRankListUseCaseTests: XCTestCase {
var massageRepository: MassageRepositorySpy!
var sut: FetchMassageRankListUseCaseImpl!

override func setUp() {
massageRepository = .init()
sut = .init(massageRepository: massageRepository)
}

override func tearDown() {
massageRepository = nil
sut = nil
}

func testFetchMassageInfo() async throws {
XCTAssertEqual(massageRepository.fetchMassageRankListCallCount, 0)
let expected = [
MassageRankModel(id: 1, rank: 2, stuNum: "1111", memberName: "κΉ€μ‹œν›ˆ", gender: .man)
]
massageRepository.fetchMassageRankListHandler = { expected }

let actual = try await sut()

XCTAssertEqual(massageRepository.fetchMassageRankListCallCount, 1)
XCTAssertEqual(actual, expected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,24 @@ final class MassageRepositoryTests: XCTestCase {

XCTAssertEqual(remoteMassageDataSource.applyMassageCallCount, 1)
}

func testCancelMassage() async throws {
XCTAssertEqual(remoteMassageDataSource.cancelMassageCallCount, 0)
try await sut.cancelMassage()

XCTAssertEqual(remoteMassageDataSource.cancelMassageCallCount, 1)
}

func testFetchMassageRankList() async throws {
XCTAssertEqual(remoteMassageDataSource.fetchMassageRankListCallCount, 0)
let expected = [
MassageRankModel(id: 1, rank: 2, stuNum: "3218", memberName: "μ „μŠΉμ›", gender: .man)
]
remoteMassageDataSource.fetchMassageRankListHandler = { expected }

let actual = try await sut.fetchMassageRankList()

XCTAssertEqual(remoteMassageDataSource.fetchMassageRankListCallCount, 1)
XCTAssertEqual(actual, expected)
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import BaseDomainInterface
import Foundation

public struct FetchSelfStudyRankSearchRequestDTO {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import BaseDomainInterface
import Foundation

public struct SelfStudyRankEntity: Equatable {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import BaseDomainInterface
import Foundation
import SelfStudyDomainInterface

Expand Down
1 change: 0 additions & 1 deletion Projects/Feature/BaseFeature/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ let project = Project.module(
name: ModulePaths.Feature.BaseFeature.rawValue,
targets: [
.implements(module: .feature(.BaseFeature), product: .framework, dependencies: [
.SPM.MSGLayout,
.SPM.Moordinator,
.SPM.Store,
.SPM.IQKeyboardManagerSwift,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
35 changes: 35 additions & 0 deletions Projects/Feature/MassageFeature/Demo/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import UIKit
import Inject
@testable import MassageFeature
@testable import MassageDomainTesting
@testable import UserDomainTesting

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?

func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let fetchMassageRankListUseCase = FetchMassageRankListUseCaseSpy()
fetchMassageRankListUseCase.fetchMassageRankListHandler = {
[
.init(id: 1, rank: 1, stuNum: "1234", memberName: "λŒ€μΆ©μ΄λ¦„", gender: .man),
.init(id: 2, rank: 2, stuNum: "1235", memberName: "λŒ€μ΄μΆ©λ¦„", gender: .man),
.init(id: 3, rank: 3, stuNum: "1236", memberName: "μ΄λ¦„λŒ€μΆ©", gender: .woman)
]
}
let store = MassageStore(
fetchMassageRankListUseCase: fetchMassageRankListUseCase
)
let viewController = Inject.ViewControllerHost(
UINavigationController(rootViewController: MassageViewController(store: store))
)
window?.rootViewController = viewController
window?.makeKeyAndVisible()

return true
}
}
12 changes: 10 additions & 2 deletions Projects/Feature/MassageFeature/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@ let project = Project.module(
targets: [
.implements(module: .feature(.MassageFeature), dependencies: [
.feature(target: .BaseFeature),
.domain(target: .AuthDomain, type: .interface)
.domain(target: .MassageDomain, type: .interface),
.domain(target: .UserDomain, type: .interface)
]),
.tests(module: .feature(.MassageFeature), dependencies: [
.feature(target: .MassageFeature)
.feature(target: .MassageFeature),
.domain(target: .MassageDomain, type: .testing),
.domain(target: .UserDomain, type: .testing)
]),
.demo(module: .feature(.MassageFeature), dependencies: [
.feature(target: .MassageFeature),
.domain(target: .MassageDomain, type: .testing),
.domain(target: .UserDomain, type: .testing)
])
]
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import MassageDomainInterface
import Swinject
import UserDomainInterface

public final class MassageAssembly: Assembly {
public init() {}
public func assemble(container: Container) {
container.register(MassageFactory.self) { _ in
MassageFactoryImpl()
container.register(MassageFactory.self) { resolver in
MassageFactoryImpl(
fetchMassageRankListUseCase: resolver.resolve(FetchMassageRankListUseCase.self)!
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import MassageDomainInterface
import Moordinator
import UserDomainInterface

struct MassageFactoryImpl: MassageFactory {
private let fetchMassageRankListUseCase: any FetchMassageRankListUseCase

init(
fetchMassageRankListUseCase: any FetchMassageRankListUseCase
) {
self.fetchMassageRankListUseCase = fetchMassageRankListUseCase
}

func makeMoordinator() -> Moordinator {
MassageMoordinator()
let store = MassageStore(
fetchMassageRankListUseCase: fetchMassageRankListUseCase
)
let viewController = MassageViewController(store: store)
return MassageMoordinator(massageViewController: viewController)
}
}
Loading
Loading