From 5f110565b5df09af83d69a7e8e72a566bfff3df2 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:50:26 +0900 Subject: [PATCH 01/14] =?UTF-8?q?:recycle:=20Task=EA=B0=90=EC=8B=B8?= =?UTF-8?q?=EB=8A=94=EA=B1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 2d570307282f76bf9cb2d9b297b13878b9a716d3) --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 1 - .../Network/Mock/MockData/PostList.json | 8 ++-- .../Scenes/Home/HomeConfigurator.swift | 3 +- .../Scenes/Login/LoginConfigurator.swift | 3 +- .../Playback/PlaybackConfigurator.swift | 3 +- .../Scenes/Playback/PlaybackInteractor.swift | 47 ++++++++++++------- .../Playback/PlaybackViewController.swift | 4 +- 7 files changed, 43 insertions(+), 26 deletions(-) diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index 1903fab..3455019 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -1436,7 +1436,6 @@ FC2511AB2B04EA6B004717BC /* MapConfigurator.swift in Sources */, 1945523B2B05258200299768 /* HomeConfigurator.swift in Sources */, FCF19BE22B2A4088003002E0 /* AVFileType+.swift in Sources */, - FC5BE11D2B148D160036366D /* EditProfileWorker.swift in Sources */, 19A1693A2B17BCC400DB34C0 /* MemberDTO.swift in Sources */, 194551F62B037F2D00299768 /* LoginViewController.swift in Sources */, FC767FA52B125F430088CF9B /* UIViewController+.swift in Sources */, diff --git a/iOS/Layover/Layover/Network/Mock/MockData/PostList.json b/iOS/Layover/Layover/Network/Mock/MockData/PostList.json index 7edcbf7..74cd412 100644 --- a/iOS/Layover/Layover/Network/Mock/MockData/PostList.json +++ b/iOS/Layover/Layover/Network/Mock/MockData/PostList.json @@ -81,8 +81,8 @@ { "member" : { "id" : 5, - "username" : "layover", - "introduce" : "Hi, my name is hwani", + "username" : "layover2", + "introduce" : "Hi, my name is hwani2", "profile_image_url" : "profile_image_link" }, "board" : { @@ -91,8 +91,8 @@ "video_thumbnail_url" : "https://res.heraldm.com/content/image/2023/04/16/20230416000040_0.jpg", "longitude" : 37.0532156213, "latitude" : 127.060123123, - "title" : "아이즈원", - "content" : "게시글 설명2", + "title" : "아이즈원2", + "content" : "게시글 설명3", "status": "COMPLETE" }, "tag" : ["해시태그1", "해시태그6"] diff --git a/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift b/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift index 340d6aa..60899fd 100644 --- a/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift +++ b/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift @@ -18,7 +18,8 @@ final class HomeConfigurator: Configurator { let router = HomeRouter() let presenter = HomePresenter() let interactor = HomeInteractor() - let homeWorker = HomeWorker() +// let homeWorker = HomeWorker() + let homeWorker = MockHomeWorker() let videoFileWorker = VideoFileWorker() let locationManager = CurrentLocationManager() diff --git a/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift b/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift index a8cb588..01bd7a4 100644 --- a/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift +++ b/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift @@ -20,7 +20,8 @@ final class LoginConfigurator: Configurator { let interactor = LoginInteractor() let presenter = LoginPresenter() // TODO: 실행 전 Worker Mock인지 확인 - let worker = LoginWorker() +// let worker = LoginWorker() + let worker = MockLoginWorker() let router = LoginRouter() router.viewController = viewController diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift index c70f516..9e45e24 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift @@ -19,7 +19,8 @@ final class PlaybackConfigurator: Configurator { let viewController: PlaybackViewController = viewController let interactor: PlaybackInteractor = PlaybackInteractor() let presenter: PlaybackPresenter = PlaybackPresenter() - let worker: PlaybackWorkerProtocol = PlaybackWorker() +// let worker: PlaybackWorkerProtocol = PlaybackWorker() + let worker: PlaybackWorkerProtocol = MockPlaybackWorker() let router: PlaybackRouter = PlaybackRouter() router.viewController = viewController diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift index b1a0153..aa01a04 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift @@ -10,7 +10,7 @@ import UIKit protocol PlaybackBusinessLogic { @discardableResult - func displayVideoList() -> Task + func displayVideoList() async func moveInitialPlaybackCell() func setInitialPlaybackCell() func leavePlaybackView() @@ -84,22 +84,35 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { // MARK: - UseCase Load Video List - func displayVideoList() -> Task { - Task { - guard let parentView: Models.ParentView, - var posts: [Post], - let worker: PlaybackWorkerProtocol else { return false } - if parentView == .map { - posts = worker.makeInfiniteScroll(posts: posts) - self.posts = posts - } - let videos: [Models.PlaybackVideo] - (videos, playbackVideoInfos) = transPostToVideo(posts) - let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) - await MainActor.run { - presenter?.presentVideoList(with: response) - } - return true + func displayVideoList() async { +// Task { +// guard let parentView: Models.ParentView, +// var posts: [Post], +// let worker: PlaybackWorkerProtocol else { return false } +// if parentView == .map { +// posts = worker.makeInfiniteScroll(posts: posts) +// self.posts = posts +// } +// let videos: [Models.PlaybackVideo] +// (videos, playbackVideoInfos) = transPostToVideo(posts) +// let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) +// await MainActor.run { +// presenter?.presentVideoList(with: response) +// } +// return true +// } + guard let parentView: Models.ParentView, + var posts: [Post], + let worker: PlaybackWorkerProtocol else { return } + if parentView == .map { + posts = worker.makeInfiniteScroll(posts: posts) + self.posts = posts + } + let videos: [Models.PlaybackVideo] + (videos, playbackVideoInfos) = transPostToVideo(posts) + let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) + await MainActor.run { + presenter?.presentVideoList(with: response) } } diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift index 9a62e6a..fd8eec8 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift @@ -92,7 +92,9 @@ final class PlaybackViewController: BaseViewController { override func viewDidLoad() { super.viewDidLoad() - interactor?.displayVideoList() + Task { + await interactor?.displayVideoList() + } interactor?.configurePlaybackCell() playbackCollectionView.delegate = self playbackCollectionView.contentInsetAdjustmentBehavior = .never From a7b4c3e3580de823a52b0b275d5502d24ddfb334 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:30:05 +0900 Subject: [PATCH 02/14] =?UTF-8?q?:recycle:=20PlaybackInteractor=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit return Task Type에서 async로 변경 (cherry picked from commit bcd0934bd10e5290bc0b0180e011f78f8a630f69) --- .../Scenes/Home/HomeConfigurator.swift | 3 +- .../Scenes/Login/LoginConfigurator.swift | 3 +- .../Playback/PlaybackConfigurator.swift | 3 +- .../Scenes/Playback/PlaybackInteractor.swift | 111 +++++++----------- .../Playback/PlaybackViewController.swift | 16 ++- 5 files changed, 55 insertions(+), 81 deletions(-) diff --git a/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift b/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift index 60899fd..340d6aa 100644 --- a/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift +++ b/iOS/Layover/Layover/Scenes/Home/HomeConfigurator.swift @@ -18,8 +18,7 @@ final class HomeConfigurator: Configurator { let router = HomeRouter() let presenter = HomePresenter() let interactor = HomeInteractor() -// let homeWorker = HomeWorker() - let homeWorker = MockHomeWorker() + let homeWorker = HomeWorker() let videoFileWorker = VideoFileWorker() let locationManager = CurrentLocationManager() diff --git a/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift b/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift index 01bd7a4..a8cb588 100644 --- a/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift +++ b/iOS/Layover/Layover/Scenes/Login/LoginConfigurator.swift @@ -20,8 +20,7 @@ final class LoginConfigurator: Configurator { let interactor = LoginInteractor() let presenter = LoginPresenter() // TODO: 실행 전 Worker Mock인지 확인 -// let worker = LoginWorker() - let worker = MockLoginWorker() + let worker = LoginWorker() let router = LoginRouter() router.viewController = viewController diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift index 9e45e24..c70f516 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackConfigurator.swift @@ -19,8 +19,7 @@ final class PlaybackConfigurator: Configurator { let viewController: PlaybackViewController = viewController let interactor: PlaybackInteractor = PlaybackInteractor() let presenter: PlaybackPresenter = PlaybackPresenter() -// let worker: PlaybackWorkerProtocol = PlaybackWorker() - let worker: PlaybackWorkerProtocol = MockPlaybackWorker() + let worker: PlaybackWorkerProtocol = PlaybackWorker() let router: PlaybackRouter = PlaybackRouter() router.viewController = viewController diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift index aa01a04..58da271 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift @@ -9,7 +9,6 @@ import UIKit protocol PlaybackBusinessLogic { - @discardableResult func displayVideoList() async func moveInitialPlaybackCell() func setInitialPlaybackCell() @@ -31,10 +30,8 @@ protocol PlaybackBusinessLogic { func resumeVideo() func moveToProfile(with request: PlaybackModels.MoveToRelativeView.Request) func moveToTagPlay(with request: PlaybackModels.MoveToRelativeView.Request) - @discardableResult - func fetchPosts() -> Task - @discardableResult - func loadProfileImageAndLocation(with request: PlaybackModels.LoadProfileImageAndLocation.Request) -> Task + func fetchPosts() async + func loadProfileImageAndLocation(with request: PlaybackModels.LoadProfileImageAndLocation.Request) async } protocol PlaybackDataStore: AnyObject { @@ -85,22 +82,6 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { // MARK: - UseCase Load Video List func displayVideoList() async { -// Task { -// guard let parentView: Models.ParentView, -// var posts: [Post], -// let worker: PlaybackWorkerProtocol else { return false } -// if parentView == .map { -// posts = worker.makeInfiniteScroll(posts: posts) -// self.posts = posts -// } -// let videos: [Models.PlaybackVideo] -// (videos, playbackVideoInfos) = transPostToVideo(posts) -// let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) -// await MainActor.run { -// presenter?.presentVideoList(with: response) -// } -// return true -// } guard let parentView: Models.ParentView, var posts: [Post], let worker: PlaybackWorkerProtocol else { return } @@ -372,59 +353,51 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { presenter?.presentTagPlay() } - func fetchPosts() -> Task { - Task { - if !isFetchReqeust { - isFetchReqeust = true - var page: Int = 0 - if parentView != .home { - page = playbackVideoInfos.count / Models.fetchPostCount + 1 - if page == currentPage { - return false - } + func fetchPosts() async { + if !isFetchReqeust { + isFetchReqeust = true + var page: Int = 0 + if parentView != .home { + page = playbackVideoInfos.count / Models.fetchPostCount + 1 + if page == currentPage { + return } - currentPage = page - var newPosts: [Post]? - switch parentView { - case .home: - newPosts = await worker?.fetchHomePosts() - case .map: - return false - case .myProfile, .otherProfile: - newPosts = await worker?.fetchProfilePosts(profileID: memberID, page: page) - case .tag: - guard let selectedTag else { return false } - newPosts = await worker?.fetchTagPosts(selectedTag: selectedTag, page: page) - default: - return false - } - guard let newPosts else { return false } - posts?.append(contentsOf: newPosts) - let videos: [Models.PlaybackVideo] - let newInfos: [Models.PlaybackInfo] - (videos, newInfos) = transPostToVideo(newPosts) - self.playbackVideoInfos.append(contentsOf: newInfos) - let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) - await MainActor.run { - presenter?.presentLoadFetchVideos(with: response) - isFetchReqeust = false - } - return true } - return false + currentPage = page + var newPosts: [Post]? + switch parentView { + case .home: + newPosts = await worker?.fetchHomePosts() + case .map: + return + case .myProfile, .otherProfile: + newPosts = await worker?.fetchProfilePosts(profileID: memberID, page: page) + case .tag: + guard let selectedTag else { return } + newPosts = await worker?.fetchTagPosts(selectedTag: selectedTag, page: page) + default: + return + } + guard let newPosts else { return } + posts?.append(contentsOf: newPosts) + let videos: [Models.PlaybackVideo] + let newInfos: [Models.PlaybackInfo] + (videos, newInfos) = transPostToVideo(newPosts) + self.playbackVideoInfos.append(contentsOf: newInfos) + let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: videos) + await MainActor.run { + presenter?.presentLoadFetchVideos(with: response) + isFetchReqeust = false + } } } - func loadProfileImageAndLocation(with request: PlaybackModels.LoadProfileImageAndLocation.Request) -> Task { - Task { - async let profileImageData = self.worker?.fetchImageData(with: request.profileImageURL) - async let location: String? = self.worker?.transLocation(latitude: request.latitude, longitude: request.longitude) - let response: Models.LoadProfileImageAndLocation.Response = Models.LoadProfileImageAndLocation.Response(curCell: request.curCell, profileImageData: await profileImageData, location: await location) - await MainActor.run { - presenter?.presentLoadProfileImageAndLocation(with: response) - return true - } - return false + func loadProfileImageAndLocation(with request: PlaybackModels.LoadProfileImageAndLocation.Request) async { + async let profileImageData = self.worker?.fetchImageData(with: request.profileImageURL) + async let location: String? = self.worker?.transLocation(latitude: request.latitude, longitude: request.longitude) + let response: Models.LoadProfileImageAndLocation.Response = Models.LoadProfileImageAndLocation.Response(curCell: request.curCell, profileImageData: await profileImageData, location: await location) + await MainActor.run { + presenter?.presentLoadProfileImageAndLocation(with: response) } } } diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift index fd8eec8..e2be130 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift @@ -272,11 +272,13 @@ extension PlaybackViewController: PlaybackDisplayLogic { } } cell.addAVPlayer(url: playbackVideo.displayedPost.board.videoURL) - self.interactor?.loadProfileImageAndLocation(with: Models.LoadProfileImageAndLocation.Request( - curCell: cell, - profileImageURL: playbackVideo.displayedPost.member.profileImageURL, - latitude: playbackVideo.displayedPost.board.latitude, - longitude: playbackVideo.displayedPost.board.longitude)) + Task { + await self.interactor?.loadProfileImageAndLocation(with: Models.LoadProfileImageAndLocation.Request( + curCell: cell, + profileImageURL: playbackVideo.displayedPost.member.profileImageURL, + latitude: playbackVideo.displayedPost.board.latitude, + longitude: playbackVideo.displayedPost.board.longitude)) + } cell.delegate = self return cell } @@ -404,7 +406,9 @@ extension PlaybackViewController: UICollectionViewDelegate { let currentOffset = scrollView.contentOffset.y let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height if maximumOffset < currentOffset { - interactor?.fetchPosts() + Task { + await interactor?.fetchPosts() + } } } } From 867e9ba63c0b985c0124c270a3173c25af9bc55f Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Mon, 8 Jan 2024 21:00:14 +0900 Subject: [PATCH 03/14] =?UTF-8?q?:recycle:=20delete=20logic=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 77c62a841bd3ff39386783384113ef7d5c5270d6) --- iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift index 58da271..8d9ff6d 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift @@ -278,7 +278,7 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { isNeedReplace: true) playbackVideoInfos.append(playbackVideoInfos[request.indexPathRow - 1]) if let posts { - self.posts?.append((posts[2])) + self.posts?.insert(posts[request.indexPathRow - 1], at: 0) } } else { response = Models.DeletePlaybackVideo.Response( From 670d9ba6de9b875a37d85563c44cd348f62f3519 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Mon, 8 Jan 2024 22:38:26 +0900 Subject: [PATCH 04/14] :white_check_mark: PlaybackPresenter Test Update (cherry picked from commit 72e548a856195ac66dae66bc355dc766bab385e9) --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 12 + .../Scenes/Playback/PlaybackPresenter.swift | 5 - .../Playback/PlaybackViewController.swift | 5 - .../Workers/PlaybackPresenterTests.swift | 417 ++++++++++++++++++ iOS/Layover/LayoverTests/Seeds.swift | 40 ++ 5 files changed, 469 insertions(+), 10 deletions(-) create mode 100644 iOS/Layover/LayoverTests/Mocks/Workers/PlaybackPresenterTests.swift diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index 3455019..d647afc 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -145,6 +145,7 @@ 835A61A22B068115002F22A5 /* PlaybackInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835A619C2B068115002F22A5 /* PlaybackInteractor.swift */; }; 835A61A62B0B4DDD002F22A5 /* Dashboard-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 835A61A52B0B4DDD002F22A5 /* Dashboard-Regular.ttf */; }; 835A61A92B0B5A31002F22A5 /* LoginConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835A61A82B0B5A31002F22A5 /* LoginConfigurator.swift */; }; + 8363A32D2B4C1CBB00772DDF /* PlaybackPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */; }; 836C33872B15A29600ECAFB0 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C33862B15A29600ECAFB0 /* Toast.swift */; }; 836C338B2B15D22C00ECAFB0 /* PlaybackConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C338A2B15D22C00ECAFB0 /* PlaybackConfigurator.swift */; }; 836C33912B17629400ECAFB0 /* MapRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C33902B17629400ECAFB0 /* MapRouter.swift */; }; @@ -402,6 +403,7 @@ 835A61A52B0B4DDD002F22A5 /* Dashboard-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Dashboard-Regular.ttf"; sourceTree = ""; }; 835A61A82B0B5A31002F22A5 /* LoginConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginConfigurator.swift; sourceTree = ""; }; 835A61AA2B0B85FD002F22A5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; + 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PlaybackPresenterTests.swift; path = LayoverTests/Mocks/Workers/PlaybackPresenterTests.swift; sourceTree = SOURCE_ROOT; }; 836C33862B15A29600ECAFB0 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; 836C338A2B15D22C00ECAFB0 /* PlaybackConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackConfigurator.swift; sourceTree = ""; }; 836C33902B17629400ECAFB0 /* MapRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapRouter.swift; sourceTree = ""; }; @@ -619,6 +621,7 @@ 194C21C72B1DF09B00C62645 /* Scenes */ = { isa = PBXGroup; children = ( + 8363A32B2B4C1C6900772DDF /* Playback */, 19AE481D2B29D02700DD4612 /* EditProfile */, 19AE48122B28C2A800DD4612 /* Setting */, 192513632B26F7BB001533FA /* TagPlayList */, @@ -869,6 +872,14 @@ path = Playback; sourceTree = ""; }; + 8363A32B2B4C1C6900772DDF /* Playback */ = { + isa = PBXGroup; + children = ( + 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */, + ); + path = Playback; + sourceTree = ""; + }; 836C33922B18436A00ECAFB0 /* Setting */ = { isa = PBXGroup; children = ( @@ -1595,6 +1606,7 @@ 192513802B277CD7001533FA /* ProfileViewControllerTests.swift in Sources */, 194C21C62B1DEE6B00C62645 /* HomePresenterTests.swift in Sources */, FC4E0C202B28B4C500152596 /* MockLocationFetcher.swift in Sources */, + 8363A32D2B4C1CBB00772DDF /* PlaybackPresenterTests.swift in Sources */, 1925137A2B273D98001533FA /* StubAuthManager.swift in Sources */, 1925136D2B26F84E001533FA /* MockTagPlayListWorker.swift in Sources */, 19AE481A2B28C2B700DD4612 /* SettingPresenterTests.swift in Sources */, diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift index 9a1a087..f62038d 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackPresenter.swift @@ -11,7 +11,6 @@ import Foundation protocol PlaybackPresentationLogic { func presentVideoList(with response: PlaybackModels.LoadPlaybackVideoList.Response) func presentLoadFetchVideos(with response: PlaybackModels.LoadPlaybackVideoList.Response) - func presentSetCellIfInfinite(with response: PlaybackModels.SetInitialPlaybackCell.Response) func presentMoveCellNext(with response: PlaybackModels.DisplayPlaybackVideo.Response) func presentSetInitialPlaybackCell(with response: PlaybackModels.SetInitialPlaybackCell.Response) func presentMoveInitialPlaybackCell(with response: PlaybackModels.SetInitialPlaybackCell.Response) @@ -50,10 +49,6 @@ final class PlaybackPresenter: PlaybackPresentationLogic { viewController?.loadFetchVideos(viewModel: viewModel) } - func presentSetCellIfInfinite(with response: PlaybackModels.SetInitialPlaybackCell.Response) { - viewController?.displayMoveCellIfinfinite(viewModel: Models.SetInitialPlaybackCell.ViewModel(indexPathRow: response.indexPathRow)) - } - // MARK: - UseCase Set Init Playback Scene func presentSetInitialPlaybackCell(with response: PlaybackModels.SetInitialPlaybackCell.Response) { diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift index e2be130..7637f57 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackViewController.swift @@ -19,7 +19,6 @@ protocol PlaybackViewControllerDelegate: AnyObject { protocol PlaybackDisplayLogic: AnyObject { func displayVideoList(viewModel: PlaybackModels.LoadPlaybackVideoList.ViewModel) func loadFetchVideos(viewModel: PlaybackModels.LoadPlaybackVideoList.ViewModel) - func displayMoveCellIfinfinite(viewModel: PlaybackModels.SetInitialPlaybackCell.ViewModel) func stopPrevPlayerAndPlayCurPlayer(viewModel: PlaybackModels.DisplayPlaybackVideo.ViewModel) func setInitialPlaybackCell(viewModel: PlaybackModels.SetInitialPlaybackCell.ViewModel) func moveInitialPlaybackCell(viewModel: PlaybackModels.SetInitialPlaybackCell.ViewModel) @@ -215,10 +214,6 @@ extension PlaybackViewController: PlaybackDisplayLogic { dataSource?.apply(currentSnapshot, animatingDifferences: true) } - func displayMoveCellIfinfinite(viewModel: Models.SetInitialPlaybackCell.ViewModel) { - playbackCollectionView.setContentOffset(.init(x: playbackCollectionView.contentOffset.x, y: playbackCollectionView.bounds.height * CGFloat(viewModel.indexPathRow)), animated: false) - } - func stopPrevPlayerAndPlayCurPlayer(viewModel: PlaybackModels.DisplayPlaybackVideo.ViewModel) { guard let tabBarHeight: CGFloat = self.tabBarController?.tabBar.frame.height else { return } if let previousCell = viewModel.previousCell { diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackPresenterTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackPresenterTests.swift new file mode 100644 index 0000000..51111fa --- /dev/null +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackPresenterTests.swift @@ -0,0 +1,417 @@ +// +// PlaybackPresenterTests.swift +// LayoverTests +// +// Created by 황지웅 on 12/12/23. +// Copyright © 2023 CodeBomber. All rights reserved. +// + +@testable import Layover +import XCTest + +final class PlaybackPresenterTests: XCTestCase { + // MARK: Subject under test + + var sut: PlaybackPresenter! + + typealias Models = PlaybackModels + + // MARK: - Test lifecycle + + override func setUp() { + super.setUp() + setupPlaybackPresenter() + + } + + override func tearDown() { + super.tearDown() + } + + // MARK: - Test setup + + func setupPlaybackPresenter() { + sut = PlaybackPresenter() + } + + // MARK: - Test doubles + + final class PlaybackDisplayLogicSpy: PlaybackDisplayLogic { + var displayVideoListDidCalled = false + var displayVideoListViewModel: Models.LoadPlaybackVideoList.ViewModel! + + var loadFetchVideosDidCalled = false + var loadFetchVideosViewModel: Models.LoadPlaybackVideoList.ViewModel! + + var setInitialPlaybackCellDidCalled = false + var setInitialPlaybackCellViewModel: Models.SetInitialPlaybackCell.ViewModel! + + var moveInitialPlaybackCellDidCalled = false + var moveInitialPlaybackCellViewModel: Models.SetInitialPlaybackCell.ViewModel! + + var stopPrevPlayerAndPlayCurPlayerDidCalled = false + var stopPrevPlayerAndPlayCurPlayerViewModel: Models.DisplayPlaybackVideo.ViewModel! + + var showPlayerSliderDidCalled = false + var showPlayerSliderViewModel: Models.DisplayPlaybackVideo.ViewModel! + + var teleportPlaybackCellDidCalled = false + var teleportPlaybackCellViewModel: Models.DisplayPlaybackVideo.ViewModel! + + var leavePlaybackViewDidCalled = false + var leavePlaybackViewViewModel: Models.DisplayPlaybackVideo.ViewModel! + + var resetVideoDidCalled = false + var resetVideoViewModel: Models.DisplayPlaybackVideo.ViewModel! + + var configureDataSourceDidCalled = false + var configureDataSourceViewModel: Models.ConfigurePlaybackCell.ViewModel! + + var setSeemoreButtonDidCalled = false + var setSeemoreButtonViewModel: Models.SetSeemoreButton.ViewModel! + + var deleteVideoDidCalled = false + var deleteVideoViewModel: Models.DeletePlaybackVideo.ViewModel! + + var routeToProfileDidCalled = false + + var routeToTagPlayDidCalled = false + + var setProfileImageAndLocationDidCalled = false + var setProfileImageAndLocationViewModel: Models.LoadProfileImageAndLocation.ViewModel! + + var seekVideoDidCalled = false + var seekVideoViewModel: Models.SeekVideo.ViewModel! + + var reportVideoDidCalled = false + + func displayVideoList(viewModel: Layover.PlaybackModels.LoadPlaybackVideoList.ViewModel) { + displayVideoListDidCalled = true + displayVideoListViewModel = viewModel + } + + func loadFetchVideos(viewModel: Layover.PlaybackModels.LoadPlaybackVideoList.ViewModel) { + loadFetchVideosDidCalled = true + loadFetchVideosViewModel = viewModel + } + + func setInitialPlaybackCell(viewModel: Layover.PlaybackModels.SetInitialPlaybackCell.ViewModel) { + setInitialPlaybackCellDidCalled = true + setInitialPlaybackCellViewModel = viewModel + } + + func moveInitialPlaybackCell(viewModel: Layover.PlaybackModels.SetInitialPlaybackCell.ViewModel) { + moveInitialPlaybackCellDidCalled = true + moveInitialPlaybackCellViewModel = viewModel + } + + func stopPrevPlayerAndPlayCurPlayer(viewModel: Layover.PlaybackModels.DisplayPlaybackVideo.ViewModel) { + stopPrevPlayerAndPlayCurPlayerDidCalled = true + stopPrevPlayerAndPlayCurPlayerViewModel = viewModel + } + + func showPlayerSlider(viewModel: Layover.PlaybackModels.DisplayPlaybackVideo.ViewModel) { + showPlayerSliderDidCalled = true + showPlayerSliderViewModel = viewModel + } + + func teleportPlaybackCell(viewModel: Layover.PlaybackModels.DisplayPlaybackVideo.ViewModel) { + teleportPlaybackCellDidCalled = true + teleportPlaybackCellViewModel = viewModel + } + + func leavePlaybackView(viewModel: Layover.PlaybackModels.DisplayPlaybackVideo.ViewModel) { + leavePlaybackViewDidCalled = true + leavePlaybackViewViewModel = viewModel + } + + func resetVideo(viewModel: Layover.PlaybackModels.DisplayPlaybackVideo.ViewModel) { + resetVideoDidCalled = true + resetVideoViewModel = viewModel + } + + func configureDataSource(viewModel: Layover.PlaybackModels.ConfigurePlaybackCell.ViewModel) { + configureDataSourceDidCalled = true + configureDataSourceViewModel = viewModel + } + + func setSeemoreButton(viewModel: Layover.PlaybackModels.SetSeemoreButton.ViewModel) { + setSeemoreButtonDidCalled = true + setSeemoreButtonViewModel = viewModel + } + + func deleteVideo(viewModel: Layover.PlaybackModels.DeletePlaybackVideo.ViewModel) { + deleteVideoDidCalled = true + deleteVideoViewModel = viewModel + } + + func routeToProfile() { + routeToProfileDidCalled = true + } + + func routeToTagPlay() { + routeToTagPlayDidCalled = true + } + + func setProfileImageAndLocation(viewModel: Layover.PlaybackModels.LoadProfileImageAndLocation.ViewModel) { + setProfileImageAndLocationDidCalled = true + setProfileImageAndLocationViewModel = viewModel + } + + func seekVideo(viewModel: Layover.PlaybackModels.SeekVideo.ViewModel) { + seekVideoDidCalled = true + seekVideoViewModel = viewModel + } + + func reportVideo() { + reportVideoDidCalled = true + } + } + + // MARK: - Tests + + func test_presentVideoList를_호출하면_displayVideoList를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: Seeds.PlaybackVideos.videos) + + // act + sut.presentVideoList(with: response) + + // assert + XCTAssertTrue(spy.displayVideoListDidCalled, "presentProfile은 displayVideoList를 호출했다") + // videos는 Hashable + XCTAssertEqual(spy.displayVideoListViewModel.videos.first!, Seeds.PlaybackVideos.videos.first!) + XCTAssertEqual(spy.displayVideoListViewModel.videos.last!, Seeds.PlaybackVideos.videos.last!) + XCTAssertEqual(spy.displayVideoListViewModel.videos.count, 2) + } + + func test_presentLoadFetchVideos를_호출하면_loadFetchVideos를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.LoadPlaybackVideoList.Response = Models.LoadPlaybackVideoList.Response(videos: Seeds.PlaybackVideos.videos) + // act + sut.presentLoadFetchVideos(with: response) + + // assert + XCTAssertTrue(spy.loadFetchVideosDidCalled, "presentLoadFetchVideos는 loadFetchVideos를 호출했다") + XCTAssertEqual(spy.loadFetchVideosViewModel.videos.first!, Seeds.PlaybackVideos.videos.first!) + XCTAssertEqual(spy.loadFetchVideosViewModel.videos.last!, Seeds.PlaybackVideos.videos.last!) + XCTAssertEqual(spy.loadFetchVideosViewModel.videos.count, 2) + } + + func test_presentSetInitialPlaybackCell을_호출하면_setInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.SetInitialPlaybackCell.Response = Models.SetInitialPlaybackCell.Response(indexPathRow: 1) + // act + sut.presentSetInitialPlaybackCell(with: response) + + // assert + XCTAssertTrue(spy.setInitialPlaybackCellDidCalled, "presentSetInitialPlaybackCell은 setInitialPlaybackCell을 호출했다") + XCTAssertEqual(spy.setInitialPlaybackCellViewModel.indexPathRow, 1) + } + + func test_presentMoveInitialPlaybackCell을_호출하면_moveInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.SetInitialPlaybackCell.Response = Models.SetInitialPlaybackCell.Response(indexPathRow: 1) + // act + sut.presentMoveInitialPlaybackCell(with: response) + + // assert + XCTAssertTrue(spy.moveInitialPlaybackCellDidCalled, "presentMoveInitialPlaybackCell은 moveInitialPlaybackCell을 호출했다") + XCTAssertEqual(spy.moveInitialPlaybackCellViewModel.indexPathRow, 1) + } + + func test_presentMoveCellNext를_호출하면_stopPrevPlayerAndPlayCurPlayer를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.DisplayPlaybackVideo.Response = Models.DisplayPlaybackVideo.Response(previousCell: Seeds.PlaybackVideo.previousCell, currentCell: Seeds.PlaybackVideo.currentCell) + // act + sut.presentMoveCellNext(with: response) + + // assert + XCTAssertTrue(spy.stopPrevPlayerAndPlayCurPlayerDidCalled, "presentMoveCellNext는 stopPrevPlayerAndPlayCurPlayerDidCalled를 호출했다") + // 이전 PlaybackCell과 현재 PlaybackCell은 달라야함 + XCTAssertNotEqual(spy.stopPrevPlayerAndPlayCurPlayerViewModel.previousCell, spy.stopPrevPlayerAndPlayCurPlayerViewModel.currentCell) + XCTAssertEqual(spy.stopPrevPlayerAndPlayCurPlayerViewModel.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertEqual(spy.stopPrevPlayerAndPlayCurPlayerViewModel.currentCell, Seeds.PlaybackVideo.currentCell) + } + + func test_presentPlayInitialPlaybackCell을_호출하면_stopPrevPlayerAndPlayCurPlayer를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.DisplayPlaybackVideo.Response = Models.DisplayPlaybackVideo.Response(previousCell: nil, currentCell: Seeds.PlaybackVideo.currentCell) + // act + sut.presentPlayInitialPlaybackCell(with: response) + + // assert + XCTAssertTrue(spy.stopPrevPlayerAndPlayCurPlayerDidCalled, "presentPlayInitialPlaybackCell은 stopPrevPlayerAndPlayCurPlayerDidCalled를 호출했다") + XCTAssertNotEqual(spy.stopPrevPlayerAndPlayCurPlayerViewModel.previousCell, spy.stopPrevPlayerAndPlayCurPlayerViewModel.currentCell) + XCTAssertEqual(spy.stopPrevPlayerAndPlayCurPlayerViewModel.previousCell, nil) + XCTAssertEqual(spy.stopPrevPlayerAndPlayCurPlayerViewModel.currentCell, Seeds.PlaybackVideo.currentCell) + } + + func test_presentShowPlayerSlider를_호출하면_showPlayerSlider를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.DisplayPlaybackVideo.Response = Models.DisplayPlaybackVideo.Response(previousCell: nil, currentCell: Seeds.PlaybackVideo.currentCell) + // act + sut.presentShowPlayerSlider(with: response) + + // assert + XCTAssertTrue(spy.showPlayerSliderDidCalled, "presentShowPlayerSlider은 showPlayerSlider를 호출했다") + XCTAssertNotEqual(spy.showPlayerSliderViewModel.previousCell, spy.showPlayerSliderViewModel.currentCell) + XCTAssertEqual(spy.showPlayerSliderViewModel.previousCell, nil) + XCTAssertEqual(spy.showPlayerSliderViewModel.currentCell, Seeds.PlaybackVideo.currentCell) + } + + func test_presentTeleportCell을_호출하면_teleportPlaybackCell을_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.DisplayPlaybackVideo.Response = Models.DisplayPlaybackVideo.Response(indexPathRow: 3, previousCell: nil, currentCell: nil) + // act + sut.presentTeleportCell(with: response) + + // assert + XCTAssertTrue(spy.teleportPlaybackCellDidCalled, "presentTeleportCell은 teleportPlaybackCell을 호출하지 못했습니다") + XCTAssertEqual(spy.teleportPlaybackCellViewModel.indexPathRow, 3) + } + + func test_presentLeavePlaybackView를_호출하면_leavePlaybackView를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.DisplayPlaybackVideo.Response = Models.DisplayPlaybackVideo.Response(previousCell: Seeds.PlaybackVideo.previousCell, currentCell: nil) + // act + sut.presentLeavePlaybackView(with: response) + + // assert + XCTAssertTrue(spy.leavePlaybackViewDidCalled, "presentLeavePlaybackView는 teleportPlaybackCell을 호출하지 못했습니다") + XCTAssertNotEqual(spy.leavePlaybackViewViewModel.previousCell, spy.leavePlaybackViewViewModel.currentCell) + XCTAssertEqual(spy.leavePlaybackViewViewModel.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertEqual(spy.leavePlaybackViewViewModel.currentCell, nil) + } + + func test_presentResetPlaybackCell을_호출하면_resetVideo를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.DisplayPlaybackVideo.Response = Models.DisplayPlaybackVideo.Response(previousCell: nil, currentCell: Seeds.PlaybackVideo.currentCell) + // act + sut.presentResetPlaybackCell(with: response) + + // assert + XCTAssertTrue(spy.resetVideoDidCalled, "presentResetPlaybackCell은 resetVideo를 호출하지 못했습니다") + XCTAssertNotEqual(spy.resetVideoViewModel.previousCell, spy.resetVideoViewModel.currentCell) + XCTAssertEqual(spy.resetVideoViewModel.previousCell, nil) + XCTAssertEqual(spy.resetVideoViewModel.currentCell, Seeds.PlaybackVideo.currentCell) + } + + func test_presentConfigureCell을_호출하면_configureDataSource를_호출하고_올바른_데이터를_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.ConfigurePlaybackCell.Response = Models.ConfigurePlaybackCell.Response(teleportIndex: 3) + // act + sut.presentConfigureCell(with: response) + + // assert + XCTAssertTrue(spy.configureDataSourceDidCalled, "presentConfigureDataSource는 configureDataSource를 호출하지 못했습니다") + XCTAssertEqual(spy.configureDataSourceViewModel.teleportIndex, 3) + } + + func test_presentSetSeemoreButton을_호출하면_setSeemoreButton을_호출하고_올바른_데이터를_전달한다_delete() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.SetSeemoreButton.Response = Models.SetSeemoreButton.Response(buttonType: .delete, indexPathRow: 0) + // act + sut.presentSetSeemoreButton(with: response) + + // assert + XCTAssertTrue(spy.setSeemoreButtonDidCalled, "presentSetSeemoreButton은 setSeemoreButton을 호출하지 못했습니다") + XCTAssertEqual(spy.setSeemoreButtonViewModel.buttonType, .delete) + } + + func test_presentSetSeemoreButton을_호출하면_setSeemoreButton을_호출하고_올바른_데이터를_전달한다_report() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.SetSeemoreButton.Response = Models.SetSeemoreButton.Response(buttonType: .report, indexPathRow: 0) + // act + sut.presentSetSeemoreButton(with: response) + + // assert + XCTAssertTrue(spy.setSeemoreButtonDidCalled, "presentSetSeemoreButton은 setSeemoreButton을 호출하지 못했습니다") + XCTAssertEqual(spy.setSeemoreButtonViewModel.buttonType, .report) + } + + func test_presentProfile을_호출하면_routeToProfile을_호출한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + // act + sut.presentProfile() + + // assert + XCTAssertTrue(spy.routeToProfileDidCalled, "presentProfile은 routeToProfile을 호출하지 못했습니다") + } + + func test_presentTagPlay을_호출하면_routeToTagPlay을_호출한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + // act + sut.presentTagPlay() + + // assert + XCTAssertTrue(spy.routeToTagPlayDidCalled, "presentTagPlay는 routeToTagPlay를 호출하지 못했습니다") + } + + func test_presentLoadProfileImageAndLocation을_호출하면_setProfileImageAndLocation을_호출한다_nil일_경우_지역으로_이름_모를_곳을_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.LoadProfileImageAndLocation.Response = Models.LoadProfileImageAndLocation.Response(curCell: Seeds.PlaybackVideo.currentCell, profileImageData: Seeds.PlaybackVideo.profileImageData, location: nil) + // act + sut.presentLoadProfileImageAndLocation(with: response) + + // assert + XCTAssertTrue(spy.setProfileImageAndLocationDidCalled, "presentLoadProfileImageAndLocation은 setProfileImageAndLocation를 호출하지 못했습니다") + XCTAssertEqual(spy.setProfileImageAndLocationViewModel.curCell, Seeds.PlaybackVideo.currentCell) + XCTAssertEqual(spy.setProfileImageAndLocationViewModel.profileImageData, Seeds.PlaybackVideo.profileImageData) + XCTAssertEqual(spy.setProfileImageAndLocationViewModel.location, "이름 모를 곳") + } + + func test_presentLoadProfileImageAndLocation을_호출하면_setProfileImageAndLocation을_호출한다_지역이_존재할_경우_지역으로_지역이름을_전달한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.LoadProfileImageAndLocation.Response = Models.LoadProfileImageAndLocation.Response(curCell: Seeds.PlaybackVideo.currentCell, profileImageData: Seeds.PlaybackVideo.profileImageData, location: "서울특별시") + // act + sut.presentLoadProfileImageAndLocation(with: response) + + // assert + XCTAssertTrue(spy.setProfileImageAndLocationDidCalled, "presentLoadProfileImageAndLocation은 setProfileImageAndLocation를 호출하지 못했습니다") + XCTAssertEqual(spy.setProfileImageAndLocationViewModel.curCell, Seeds.PlaybackVideo.currentCell) + XCTAssertEqual(spy.setProfileImageAndLocationViewModel.profileImageData, Seeds.PlaybackVideo.profileImageData) + XCTAssertEqual(spy.setProfileImageAndLocationViewModel.location, "서울특별시") + } + + func test_presentSeekVideo를_호출하면_seekVideo를_호출한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + let response: Models.SeekVideo.Response = Models.SeekVideo.Response(willMoveLocation: 1, currentCell: Seeds.PlaybackVideo.currentCell) + // act + sut.presentSeekVideo(with: response) + + // assert + XCTAssertTrue(spy.seekVideoDidCalled, "presentSeekVideo를 호출하지 못했습니다.") + XCTAssertEqual(spy.seekVideoViewModel.willMoveLocation, 1) + XCTAssertEqual(spy.seekVideoViewModel.currentCell, Seeds.PlaybackVideo.currentCell) + } + + func test_presentReportVideo를_호출하면_reportVideo를_호출한다() { + let spy = PlaybackDisplayLogicSpy() + sut.viewController = spy + + // act + sut.presentReportVideo() + + // assert + XCTAssertTrue(spy.reportVideoDidCalled, "presentReportVideo를 호출하지 못했습니다") + } +} diff --git a/iOS/Layover/LayoverTests/Seeds.swift b/iOS/Layover/LayoverTests/Seeds.swift index 294d99c..ec3ed8b 100644 --- a/iOS/Layover/LayoverTests/Seeds.swift +++ b/iOS/Layover/LayoverTests/Seeds.swift @@ -83,4 +83,44 @@ class Seeds { introduce: "안녕하세요, 아이브의 안유진입니다.", profileImageURL: URL(string: "https://cdn.footballist.co.kr/news/photo/202307/170226_100422_1733.jpg")!) } + + struct PlaybackVideos { + static let videos: [PlaybackModels.PlaybackVideo] = + [PlaybackModels.PlaybackVideo( + displayedPost: PlaybackModels.DisplayedPost( + member: PlaybackModels.Member( + memberID: 1, + username: "안유진", + profileImageURL: URL(string: "https://cdn.footballist.co.kr/news/photo/202307/170226_100422_1733.jpg")), + board: PlaybackModels.Board( + boardID: 1, + title: "최강 아이돌", + description: "게시글 설명", + videoURL: URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8")!, + latitude: 127.060123123, + longitude: 37.0532156213), + tags: ["아이브", "yujin"])), + PlaybackModels.PlaybackVideo( + displayedPost: PlaybackModels.DisplayedPost( + member: PlaybackModels.Member( + memberID: 2, + username: "장원영", + profileImageURL: URL(string: "https://www.fnnews.com/resource/media/image/2023/10/17/202310171126334525_l.jpg")), + board: PlaybackModels.Board( + boardID: 2, + title: "아이브의 멤버", + description: "게시글 설명설명설명", + videoURL: URL(string: "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8")!, + latitude: 100.060123123, + longitude: 35.001828282), + tags: ["Ive", "wonyoung"])) + ] + } + + enum PlaybackVideo { + static let previousCell: PlaybackCell = PlaybackCell() + static let currentCell: PlaybackCell = PlaybackCell() + static let profileImageData: Data? = try? Data(contentsOf: Bundle(for: Seeds.self).url(forResource: "sample", withExtension: "jpeg")!) + static let url: URL? = URL(string: "https://www.fnnews.com/resource/media/image/2023/10/17/202310171126334525_l.jpg") + } } From 17ee86e05c9825ad765a745c70a591a1f8f9c78b Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Tue, 9 Jan 2024 00:39:21 +0900 Subject: [PATCH 05/14] =?UTF-8?q?:white=5Fcheck=5Fmark:=20PlaybackInteract?= =?UTF-8?q?or=20Test=201=EC=B0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 166e75680d655f153bedc13d136f63c308cff18c) --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 4 + .../Scenes/Playback/PlaybackInteractor.swift | 2 +- .../Workers/Mocks/MockPlaybackWorker.swift | 13 +- .../Workers/PlaybackInteractorTests.swift | 652 ++++++++++++++++++ 4 files changed, 666 insertions(+), 5 deletions(-) create mode 100644 iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index d647afc..e31f751 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -146,6 +146,7 @@ 835A61A62B0B4DDD002F22A5 /* Dashboard-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 835A61A52B0B4DDD002F22A5 /* Dashboard-Regular.ttf */; }; 835A61A92B0B5A31002F22A5 /* LoginConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835A61A82B0B5A31002F22A5 /* LoginConfigurator.swift */; }; 8363A32D2B4C1CBB00772DDF /* PlaybackPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */; }; + 8363A32F2B4C329100772DDF /* PlaybackInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8363A32E2B4C329100772DDF /* PlaybackInteractorTests.swift */; }; 836C33872B15A29600ECAFB0 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C33862B15A29600ECAFB0 /* Toast.swift */; }; 836C338B2B15D22C00ECAFB0 /* PlaybackConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C338A2B15D22C00ECAFB0 /* PlaybackConfigurator.swift */; }; 836C33912B17629400ECAFB0 /* MapRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C33902B17629400ECAFB0 /* MapRouter.swift */; }; @@ -404,6 +405,7 @@ 835A61A82B0B5A31002F22A5 /* LoginConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginConfigurator.swift; sourceTree = ""; }; 835A61AA2B0B85FD002F22A5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PlaybackPresenterTests.swift; path = LayoverTests/Mocks/Workers/PlaybackPresenterTests.swift; sourceTree = SOURCE_ROOT; }; + 8363A32E2B4C329100772DDF /* PlaybackInteractorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PlaybackInteractorTests.swift; path = LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift; sourceTree = SOURCE_ROOT; }; 836C33862B15A29600ECAFB0 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; 836C338A2B15D22C00ECAFB0 /* PlaybackConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackConfigurator.swift; sourceTree = ""; }; 836C33902B17629400ECAFB0 /* MapRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapRouter.swift; sourceTree = ""; }; @@ -876,6 +878,7 @@ isa = PBXGroup; children = ( 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */, + 8363A32E2B4C329100772DDF /* PlaybackInteractorTests.swift */, ); path = Playback; sourceTree = ""; @@ -1612,6 +1615,7 @@ 19AE481A2B28C2B700DD4612 /* SettingPresenterTests.swift in Sources */, 19AE48172B28C2B700DD4612 /* SettingViewControllerTests.swift in Sources */, 194C21C32B1DEE6B00C62645 /* HomeViewControllerTests.swift in Sources */, + 8363A32F2B4C329100772DDF /* PlaybackInteractorTests.swift in Sources */, 192513692B26F7CE001533FA /* TagPlayListInteractorTests.swift in Sources */, 19AE48232B29D03D00DD4612 /* EditProfileInteractorTests.swift in Sources */, 194C21CC2B1DF39200C62645 /* MockHomeWorker.swift in Sources */, diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift index 8d9ff6d..ef93b5a 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift @@ -77,7 +77,7 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { private var currentPage: Int = 1 - private var playbackVideoInfos: [Models.PlaybackInfo] = [] + var playbackVideoInfos: [Models.PlaybackInfo] = [] // MARK: - UseCase Load Video List diff --git a/iOS/Layover/Layover/Workers/Mocks/MockPlaybackWorker.swift b/iOS/Layover/Layover/Workers/Mocks/MockPlaybackWorker.swift index 0a418b5..58d4dd4 100644 --- a/iOS/Layover/Layover/Workers/Mocks/MockPlaybackWorker.swift +++ b/iOS/Layover/Layover/Workers/Mocks/MockPlaybackWorker.swift @@ -27,10 +27,15 @@ final class MockPlaybackWorker: PlaybackWorkerProtocol { } func makeInfiniteScroll(posts: [Post]) -> [Post] { - guard let tempLastVideo: Post = posts.last, - let tempFirstVideo: Post = posts.first - else { return posts } - var tempVideos: [Post] = posts + var tempVideos: [Post] = [] + for post in posts { + if post.board.videoURL != nil, post.board.status == .complete { + tempVideos.append(post) + } + } + guard let tempLastVideo: Post = tempVideos.last, + let tempFirstVideo: Post = tempVideos.first + else { return tempVideos } tempVideos.insert(tempLastVideo, at: 0) tempVideos.append(tempFirstVideo) return tempVideos diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift new file mode 100644 index 0000000..1483b34 --- /dev/null +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift @@ -0,0 +1,652 @@ +// +// PlaybackInteractorTests.swift +// LayoverTests +// +// Created by 황지웅 on 12/12/23. +// Copyright © 2023 CodeBomber. All rights reserved. +// + +@testable import Layover +import XCTest + +final class PlaybackInteractorTests: XCTestCase { + // MARK: Subject under test + + var sut: PlaybackInteractor! + + // MARK: Properties + + typealias Models = PlaybackModels + + // MARK: - Test lifecycle + + override func setUp() { + super.setUp() + setupPlaybackInteracotr() + } + + override func tearDown() { + super.tearDown() + } + + // MARK: - Test setup + + func setupPlaybackInteracotr() { + sut = PlaybackInteractor() + sut.worker = MockPlaybackWorker() + } + + // MARK: - Test doubles + + final class PlaybackPresentationLogicSpy: PlaybackPresentationLogic { + var presentVideoListDidCalled = false + var presentVideoListResponse: Models.LoadPlaybackVideoList.Response! + + var presentLoadFetchVideosDidCalled = false + var presentLoadFetchVideosResponse: Models.LoadPlaybackVideoList.Response! + + var presentSetInitialPlaybackCellDidCalled = false + var presentSetInitialPlaybackCellResponse: Models.SetInitialPlaybackCell.Response! + + var presentMoveInitialPlaybackCellDidCalled = false + var presentMoveInitialPlaybackCellResponse: Models.SetInitialPlaybackCell.Response! + + var presentMoveCellNextDidCalled = false + var presentMoveCellNextResponse: Models.DisplayPlaybackVideo.Response! + + var presentPlayInitialPlaybackCellDidCalled = false + var presentPlayInitialPlaybackCellResponse: Models.DisplayPlaybackVideo.Response! + + var presentShowPlayerSliderDidCalled = false + var presentShowPlayerSliderResponse: Models.DisplayPlaybackVideo.Response! + + var presentTeleportCellDidCalled = false + var presentTeleportCellResponse: Models.DisplayPlaybackVideo.Response! + + var presentLeavePlaybackViewDidCalled = false + var presentLeavePlaybackViewResponse: Models.DisplayPlaybackVideo.Response! + + var presentResetPlaybackCellDidCalled = false + var presentResetPlaybackCellResponse: Models.DisplayPlaybackVideo.Response! + + var presentConfigureCellDidCalled = false + var presentConfigureCellResponse: Models.ConfigurePlaybackCell.Response! + + var presentSetSeemoreButtonDidCalled = false + var presentSetSeemoreButtonResponse: Models.SetSeemoreButton.Response! + + var presentDeleteVideoDidCalled = false + var presentDeleteVideoResponse: Models.DeletePlaybackVideo.Response! + + var presentProfileDidCalled = false + + var presentTagPlayDidCalled = false + + var presentLoadProfileImageAndLocationDidCalled = false + var presentLoadProfileImageAndLocationResponse: Models.LoadProfileImageAndLocation.Response! + + var presentSeekVideoDidCalled = false + var presentSeekVideoResponse: Models.SeekVideo.Response! + + var presentReportVideoDidCalled = false + + func presentVideoList(with response: Layover.PlaybackModels.LoadPlaybackVideoList.Response) { + presentVideoListDidCalled = true + presentVideoListResponse = response + } + + func presentLoadFetchVideos(with response: Layover.PlaybackModels.LoadPlaybackVideoList.Response) { + presentLoadFetchVideosDidCalled = true + presentLoadFetchVideosResponse = response + } + + func presentSetInitialPlaybackCell(with response: Layover.PlaybackModels.SetInitialPlaybackCell.Response) { + presentSetInitialPlaybackCellDidCalled = true + presentSetInitialPlaybackCellResponse = response + } + + func presentMoveInitialPlaybackCell(with response: Layover.PlaybackModels.SetInitialPlaybackCell.Response) { + presentMoveInitialPlaybackCellDidCalled = true + presentMoveInitialPlaybackCellResponse = response + } + + func presentMoveCellNext(with response: Layover.PlaybackModels.DisplayPlaybackVideo.Response) { + presentMoveCellNextDidCalled = true + presentMoveCellNextResponse = response + } + + func presentPlayInitialPlaybackCell(with response: Layover.PlaybackModels.DisplayPlaybackVideo.Response) { + presentPlayInitialPlaybackCellDidCalled = true + presentPlayInitialPlaybackCellResponse = response + } + + func presentShowPlayerSlider(with response: Layover.PlaybackModels.DisplayPlaybackVideo.Response) { + presentShowPlayerSliderDidCalled = true + presentShowPlayerSliderResponse = response + } + + func presentTeleportCell(with response: Layover.PlaybackModels.DisplayPlaybackVideo.Response) { + presentTeleportCellDidCalled = true + presentTeleportCellResponse = response + } + + func presentLeavePlaybackView(with response: Layover.PlaybackModels.DisplayPlaybackVideo.Response) { + presentLeavePlaybackViewDidCalled = true + presentLeavePlaybackViewResponse = response + } + + func presentResetPlaybackCell(with response: Layover.PlaybackModels.DisplayPlaybackVideo.Response) { + presentResetPlaybackCellDidCalled = true + presentResetPlaybackCellResponse = response + } + + func presentConfigureCell(with response: Layover.PlaybackModels.ConfigurePlaybackCell.Response) { + presentConfigureCellDidCalled = true + presentConfigureCellResponse = response + } + + func presentSetSeemoreButton(with response: Layover.PlaybackModels.SetSeemoreButton.Response) { + presentSetSeemoreButtonDidCalled = true + presentSetSeemoreButtonResponse = response + } + + func presentDeleteVideo(with response: Layover.PlaybackModels.DeletePlaybackVideo.Response) { + presentDeleteVideoDidCalled = true + presentDeleteVideoResponse = response + } + + func presentProfile() { + presentProfileDidCalled = true + } + + func presentTagPlay() { + presentTagPlayDidCalled = true + } + + func presentLoadProfileImageAndLocation(with response: Layover.PlaybackModels.LoadProfileImageAndLocation.Response) { + presentLoadProfileImageAndLocationDidCalled = true + presentLoadProfileImageAndLocationResponse = response + } + + func presentSeekVideo(with response: Layover.PlaybackModels.SeekVideo.Response) { + presentSeekVideoDidCalled = true + presentSeekVideoResponse = response + } + + func presentReportVideo() { + presentReportVideoDidCalled = true + } + } + + // MARK: - Tests + + func test_parentView가_map일_때_displayVideoList를_호출하면_presentVideoList를_호출하고_올바른_데이터를_전달한다() async { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.presenter = spy + sut.parentView = .map + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.videoURLNilPost] + + // Act + await sut.displayVideoList() + + // Assert + XCTAssertTrue(spy.presentVideoListDidCalled, "displayVideoList는 presentVideoList를 호출하지 않았습니다") + // map이므로 2 + 더미셀 2 = 4 + // videoURL이 nil이면 거름 + print(spy.presentVideoListResponse.videos) + XCTAssertEqual(spy.presentVideoListResponse.videos.count, 4) + XCTAssertEqual(spy.presentVideoListResponse.videos[0].displayedPost, spy.presentVideoListResponse.videos[2].displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos[1].displayedPost, spy.presentVideoListResponse.videos[1].displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos.first!.displayedPost, Seeds.PlaybackVideos.videos.last!.displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos.last!.displayedPost, Seeds.PlaybackVideos.videos.first!.displayedPost) + } + + func test_displayVideoList를_호출하면_presentVideoList를_호출하고_올바른_데이터를_전달한다_parentView가_map이_아닐때() async { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.presenter = spy + sut.parentView = .home + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.videoURLNilPost] + + // Act + await sut.displayVideoList() + + // Assert + XCTAssertTrue(spy.presentVideoListDidCalled, "displayVideoList는 presentVideoList를 호출하지 않았습니다") + // map이므로 2 + 더미셀 2 = 4 + // videoURL이 nil이면 거름 + XCTAssertEqual(spy.presentVideoListResponse.videos.count, 2) + XCTAssertEqual(spy.presentVideoListResponse.videos.first!.displayedPost, Seeds.PlaybackVideos.videos.first!.displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos.last!.displayedPost, Seeds.PlaybackVideos.videos.last!.displayedPost) + } + + func test_moveInitialPlaybackCell을_호출하면_presentMoveInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다_parentView가_map일_때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .map + sut.index = 2 + sut.presenter = spy + + // Act + sut.moveInitialPlaybackCell() + + // Assert + XCTAssertTrue(spy.presentMoveInitialPlaybackCellDidCalled, "moveInitialPlaybackCell은 moveInitialPlaybackCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentMoveInitialPlaybackCellResponse.indexPathRow, 3) + } + + func test_moveInitialPlaybackCell을_호출하면_presentMoveInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다_parentView가_map이_아닐때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .home + sut.index = 2 + sut.presenter = spy + + // Act + sut.moveInitialPlaybackCell() + + // Assert + XCTAssertTrue(spy.presentMoveInitialPlaybackCellDidCalled, "moveInitialPlaybackCell은 moveInitialPlaybackCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentMoveInitialPlaybackCellResponse.indexPathRow, 2) + } + + func test_setInitialPlaybackCell을_호출하면_presentSetInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다_parentView가_map일_때() { + // Arraynge + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .map + sut.index = 2 + sut.presenter = spy + + // Act + sut.setInitialPlaybackCell() + + // Assert + XCTAssertTrue(spy.presentSetInitialPlaybackCellDidCalled, "setInitialPlaybackCell은 presentSetInitialPlaybackCell을 호출하지 않았습니다.") + XCTAssertEqual(spy.presentSetInitialPlaybackCellResponse.indexPathRow, 3) + } + + func test_setInitialPlaybackCell을_호출하면_presentSetInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다_parentView가_map이_아닐때() { + // Arraynge + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .map + sut.index = 2 + sut.presenter = spy + + // Act + sut.setInitialPlaybackCell() + + // Assert + XCTAssertTrue(spy.presentSetInitialPlaybackCellDidCalled, "setInitialPlaybackCell은 presentSetInitialPlaybackCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentSetInitialPlaybackCellResponse.indexPathRow, 3) + } + + func test_playInitialPlaybackCell을_호출하면_presentPlayInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: nil, currentCell: Seeds.PlaybackVideo.currentCell) + sut.presenter = spy + // Act + sut.playInitialPlaybackCell(with: request) + + // Assert + XCTAssertTrue(spy.presentPlayInitialPlaybackCellDidCalled, "playInitialPlaybackCell은 presentInitialPlaybackCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentPlayInitialPlaybackCellResponse.previousCell, nil) + XCTAssertEqual(spy.presentPlayInitialPlaybackCellResponse.currentCell, sut.previousCell) + XCTAssertEqual(spy.presentPlayInitialPlaybackCellResponse.currentCell, Seeds.PlaybackVideo.currentCell) + } + + func test_playVideo를_호출할_때_이전Cell과_현재Cell이_동일하면_presentShowPlayerSlider를_호출한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.videoURLNilPost] + sut.previousCell = Seeds.PlaybackVideo.currentCell + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: nil, currentCell: Seeds.PlaybackVideo.currentCell) + sut.presenter = spy + // Act + sut.playVideo(with: request) + + // Assert + XCTAssertTrue(spy.presentShowPlayerSliderDidCalled, "playVideo는 presentShowPlayerSlider를 호출하지 않았습니다") + XCTAssertEqual(spy.presentShowPlayerSliderResponse.currentCell, request.currentCell) + } + +// func test_playVideo를_호출하면_presentMoveCellNext를_호출한다_parentView가_map이고_index가_마지막을_가리킬_떄() { +// // Arrange +// let spy = PlaybackPresentationLogicSpy() +// sut.parentView = .map +// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] +// sut.previousCell = Seeds.PlaybackVideo.previousCell +// let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) +// sut.presenter = spy +// // act +// sut.playVideo(with: request) +// +// // Assert +// XCTAssertTrue(spy.presentTeleportCellDidCalled, "playVideo는 presentTeleportCell를 호출하지 않았습니다") +// XCTAssertEqual(sut.previousCell, Seeds.PlaybackVideo.previousCell) +// XCTAssertEqual(spy.presentTeleportCellResponse.previousCell, Seeds.PlaybackVideo.previousCell) +// XCTAssertEqual(spy.presentTeleportCellResponse.indexPathRow, 1) +// XCTAssertTrue(((sut.isTeleport) != nil)) +// } + +// func test_playVideo를_호출하면_presentMoveCellNext를_호출한다_parentView가_map이고_index가_처음을_가리킬_떄() { +// // Arrange +// let spy = PlaybackPresentationLogicSpy() +// sut.parentView = .map +// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] +// sut.previousCell = Seeds.PlaybackVideo.previousCell +// let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) +// sut.presenter = spy +// // act +// sut.playVideo(with: request) +// +// // Assert +// XCTAssertTrue(spy.presentTeleportCellDidCalled, "playVideo는 presentTeleportCell를 호출하지 않았습니다") +// XCTAssertEqual(spy.presentTeleportCellResponse.previousCell, Seeds.PlaybackVideo.previousCell) +// XCTAssertEqual(spy.presentTeleportCellResponse.currentCell, nil) +// XCTAssertEqual(spy.presentTeleportCellResponse.indexPathRow, 0) +// XCTAssertTrue(((sut.isTeleport) != nil)) +// } + + func test_playVideo를_호출하면_presentMoveCellNext를_호출한다_parentView가_map이고_텔레포트가_필요없는_상황일_때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .map + sut.previousCell = Seeds.PlaybackVideo.previousCell + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost] + sut.previousCell = Seeds.PlaybackVideo.previousCell + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) + sut.presenter = spy + + // act + sut.playVideo(with: request) + + // Assert + XCTAssertTrue(spy.presentMoveCellNextDidCalled, "playVideo는 presentMoveCellNext를 호출하지 않았습니다") + XCTAssertEqual(sut.previousCell, Seeds.PlaybackVideo.currentCell) + XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertEqual(spy.presentMoveCellNextResponse.currentCell, Seeds.PlaybackVideo.currentCell) + XCTAssertEqual(spy.presentMoveCellNextResponse.indexPathRow, nil) + if let isTeleport = sut.isTeleport { + XCTAssertFalse(isTeleport) + } else { + XCTFail() + } + } + + func test_playTeleportVideo를_호출하면_presentMoveCellNext를_호출한다_무한스크롤상황일_때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost] + sut.isTeleport = true + sut.previousCell = Seeds.PlaybackVideo.previousCell + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) + sut.presenter = spy + + // act + sut.playTeleportVideo(with: request) + + // Assert + XCTAssertTrue(spy.presentMoveCellNextDidCalled, "playTeleportvideo는 presentMoveCellNext를 호출하지 않았습니다") + XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertEqual(spy.presentMoveCellNextResponse.currentCell, Seeds.PlaybackVideo.currentCell) + XCTAssertEqual(sut.previousCell, Seeds.PlaybackVideo.currentCell) + if let isTeleport = sut.isTeleport { + XCTAssertFalse(isTeleport) + } else { + XCTFail() + } + } + + func test_playTeleportVideo를_호출하면_presentMoveCellNext를_호출한다_셀이_삭제되는_상황일_때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost] + sut.isTeleport = true + sut.previousCell = Seeds.PlaybackVideo.previousCell + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) + sut.presenter = spy + // act + sut.playTeleportVideo(with: request) + + // Assert + XCTAssertTrue(spy.presentMoveCellNextDidCalled, "playTeleportvideo는 presentMoveCellNext를 호출하지 않았습니다") + XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertEqual(spy.presentMoveCellNextResponse.currentCell, Seeds.PlaybackVideo.currentCell) + XCTAssertEqual(sut.previousCell, Seeds.PlaybackVideo.currentCell) + XCTAssertFalse(((sut.isDelete) != nil)) + } + + func test_resumePlaybackView를_호출할때_previousCell이_존재하면_presentPlayInitialPlaybackCell을_호출한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.previousCell = Seeds.PlaybackVideo.previousCell + sut.presenter = spy + + // act + sut.resumePlaybackView() + + // Assert + XCTAssertTrue(spy.presentPlayInitialPlaybackCellDidCalled, "resumPlaybackView가 presentPlayInitialPlaybackCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentPlayInitialPlaybackCellResponse.currentCell, Seeds.PlaybackVideo.previousCell) + XCTAssertEqual(spy.presentPlayInitialPlaybackCellResponse.previousCell, nil) + } + + func test_resumePlaybackView를_호출할때_previousCell이_존재하면_presentSetInitialPlaybackCell을_호출한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.index = 2 + sut.presenter = spy + + // act + sut.resumePlaybackView() + + // Assert + XCTAssertTrue(spy.presentSetInitialPlaybackCellDidCalled, "resumPlaybackView가 presentSetInitialPlaybackCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentSetInitialPlaybackCellResponse.indexPathRow, 2) + } + + func test_leavePlaybackView를_호출할때_presentLeavePlaybackView를_호출한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.previousCell = Seeds.PlaybackVideo.previousCell + sut.presenter = spy + // act + sut.leavePlaybackView() + + // Assert + XCTAssertTrue(spy.presentLeavePlaybackViewDidCalled, "leavePlaybackView가 presentLeavePlaybackView를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLeavePlaybackViewResponse.previousCell, Seeds.PlaybackVideo.previousCell) + } + + func test_resetVideo를_호출할때_presentResetPlaybackCell을_호출한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.previousCell = Seeds.PlaybackVideo.previousCell + sut.presenter = spy + // act + sut.resetVideo() + + // Assert + XCTAssertTrue(spy.presentResetPlaybackCellDidCalled, "resetVideo가 presentResetPlaybackCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentResetPlaybackCellResponse.previousCell, nil) + XCTAssertEqual(spy.presentResetPlaybackCellResponse.currentCell, Seeds.PlaybackVideo.previousCell) + } + + func test_careVideoLoading을_호출할때_presentMoveCellNext를_호출하지않는다_previousCell이_존재할때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.previousCell = Seeds.PlaybackVideo.previousCell + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: nil, currentCell: nil) + // act + sut.careVideoLoading(with: request) + + // Assert + XCTAssertFalse(spy.presentMoveCellNextDidCalled, "careVideoLoading은 presentMoveCellNext를 호출하지 않았습니다") + } + + func test_careVideoLoading을_호출할때_presentMoveCellNext를_호출하지않는다_previousCell이_존재하지않을때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.previousCell = nil + sut.presenter = spy + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: nil, currentCell: Seeds.PlaybackVideo.currentCell) + // act + sut.careVideoLoading(with: request) + + // Assert + XCTAssertTrue(spy.presentMoveCellNextDidCalled, "careVideoLoading은 presentMoveCellNext를 호출하지 않았습니다") + XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, nil) + XCTAssertEqual(spy.presentMoveCellNextResponse.currentCell, Seeds.PlaybackVideo.currentCell) + } + + func test_configurePlaybackCell을_호출할때_presentConfigureCell을_호출한다_map일때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost] + sut.parentView = .map + sut.presenter = spy + + // act + sut.configurePlaybackCell() + + // Assert + XCTAssertTrue(spy.presentConfigureCellDidCalled, "configurePlaybackCell은 presentConfigureCell을 호출하지 않았습니다") + XCTAssertEqual(spy.presentConfigureCellResponse.teleportIndex, 4) + } + + func test_configurePlaybackCell을_호출할때_presentConfigureCell을_호출한다_map이_아닐때() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost] + sut.parentView = .home + sut.presenter = spy + + // act + sut.configurePlaybackCell() + + // Assert + XCTAssertTrue(spy.presentConfigureCellDidCalled, "configurePlaybackCell은 presentConfigureCell을 호출하지 않았습니다") + } + + func test_setSeemoreButton을_호출할때_presentSetSeemoreButton을_호출하고_올바른_데이터를_전달한다_본인일경우() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.previousCell = Seeds.PlaybackVideo.previousCell + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: -1, boardID: -1)] + sut.presenter = spy + + // act + sut.setSeeMoreButton(with: Models.SetSeemoreButton.Request(indexPathRow: 0)) + + // Assert + XCTAssertTrue(spy.presentSetSeemoreButtonDidCalled, "") + XCTAssertEqual(spy.presentSetSeemoreButtonResponse.buttonType, .delete) + } + + func test_본인이아닐경우_setSeemoreButton을_호출할때_presentSetSeemoreButton을_호출하고_올바른_데이터를_전달한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.previousCell = Seeds.PlaybackVideo.previousCell + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 1, boardID: -1)] + sut.presenter = spy + + // act + sut.setSeeMoreButton(with: Models.SetSeemoreButton.Request(indexPathRow: 0)) + + // Assert + XCTAssertTrue(spy.presentSetSeemoreButtonDidCalled, "") + XCTAssertEqual(spy.presentSetSeemoreButtonResponse.buttonType, .report) + } + + func test_moveToProfile을_호출할때_presentProfile이_호출된다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + let request: Models.MoveToRelativeView.Request = Models.MoveToRelativeView.Request(indexPathRow: 0, selectedTag: "테스트") + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 1, boardID: -1)] + sut.presenter = spy + + // act + sut.moveToProfile(with: request) + + // Assert + XCTAssertTrue(spy.presentProfileDidCalled, "moveToProfile이 presentProfileDidCalled를 호출하지 않았습니다") + XCTAssertEqual(sut.memberID, 1) + } + + func test_moveToTagPlay를_호출할때_presentTagPlay가_호출된다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + let request: Models.MoveToRelativeView.Request = Models.MoveToRelativeView.Request(indexPathRow: 0, selectedTag: "테스트") + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 1, boardID: -1)] + sut.presenter = spy + + // act + sut.moveToTagPlay(with: request) + + // Assert + XCTAssertTrue(spy.presentTagPlayDidCalled, "moveToTagPlay이 presentTagPlay를 호출하지 않았습니다") + XCTAssertEqual(sut.selectedTag, "테스트") + } + +// func test_fetchPosts를_호출하면_presentLoadFetchVideosResponse를_호출한다_Home() async { +// // Arrange +// let spy = PlaybackPresentationLogicSpy() +// sut.parentView = .home +// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] +// sut.presenter = spy +// sut.isFetchReqeust = false +// sut.currentPage = 1 +// +// // act +// let result = await sut.fetchPosts().value +// +// // Assert +// XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") +// XCTAssertTrue(result, "fetchPost에 실패했습니다.") +// XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) +// XCTAssertEqual(sut.posts?.count, 3) +// } +// +// func test_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다_tag() async throws { +// // Arrange +// let spy = PlaybackPresentationLogicSpy() +// sut.parentView = .tag +// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2] +// sut.selectedTag = "테스트" +// sut.presenter = spy +// sut.isFetchReqeust = false +// sut.currentPage = 1 +// +// // act +// let result = await sut.fetchPosts().value +// try await Task.sleep(nanoseconds: 3_000_000_000) +// +// // Assert +// XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") +// XCTAssertTrue(result, "fetchPost에 실패했습니다.") +// XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) +// XCTAssertEqual(sut.posts?.count, 21) +// } +// +// func test_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다_Profile() async throws { +// // Arrange +// let spy = PlaybackPresentationLogicSpy() +// sut.parentView = .otherProfile +// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2] +// sut.presenter = spy +// sut.memberID = -1 +// sut.isFetchReqeust = false +// sut.currentPage = 1 +// +// // act +// let result = await sut.fetchPosts().value +// +// // Assert +// XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") +// XCTAssertTrue(result, "fetchPost에 실패했습니다.") +// XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) +// XCTAssertEqual(sut.posts?.count, 21) +// } +} From 55835c79f8f544fff03819b92dd85e3961da7904 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Tue, 9 Jan 2024 22:23:03 +0900 Subject: [PATCH 06/14] =?UTF-8?q?:white=5Fcheck=5Fmark:=20PlaybackInteract?= =?UTF-8?q?or=20Test=202=EC=B0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 244a6cac3eae0f8aadc8a43a0eeda476ff073bea) --- iOS/Layover/Layover.xcodeproj/project.pbxproj | 4 + .../Scenes/Playback/PlaybackInteractor.swift | 2 +- .../Mocks/Workers/MockPlaybackWorker.swift | 177 +++++++++ .../Workers/PlaybackInteractorTests.swift | 360 +++++++++++++----- iOS/Layover/LayoverTests/Seeds.swift | 2 +- 5 files changed, 448 insertions(+), 97 deletions(-) create mode 100644 iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift diff --git a/iOS/Layover/Layover.xcodeproj/project.pbxproj b/iOS/Layover/Layover.xcodeproj/project.pbxproj index e31f751..2c80ebc 100644 --- a/iOS/Layover/Layover.xcodeproj/project.pbxproj +++ b/iOS/Layover/Layover.xcodeproj/project.pbxproj @@ -147,6 +147,7 @@ 835A61A92B0B5A31002F22A5 /* LoginConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835A61A82B0B5A31002F22A5 /* LoginConfigurator.swift */; }; 8363A32D2B4C1CBB00772DDF /* PlaybackPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */; }; 8363A32F2B4C329100772DDF /* PlaybackInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8363A32E2B4C329100772DDF /* PlaybackInteractorTests.swift */; }; + 8363A3332B4D6E9B00772DDF /* MockPlaybackWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8363A3322B4D6E9B00772DDF /* MockPlaybackWorker.swift */; }; 836C33872B15A29600ECAFB0 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C33862B15A29600ECAFB0 /* Toast.swift */; }; 836C338B2B15D22C00ECAFB0 /* PlaybackConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C338A2B15D22C00ECAFB0 /* PlaybackConfigurator.swift */; }; 836C33912B17629400ECAFB0 /* MapRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 836C33902B17629400ECAFB0 /* MapRouter.swift */; }; @@ -406,6 +407,7 @@ 835A61AA2B0B85FD002F22A5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; 8363A32C2B4C1CBA00772DDF /* PlaybackPresenterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PlaybackPresenterTests.swift; path = LayoverTests/Mocks/Workers/PlaybackPresenterTests.swift; sourceTree = SOURCE_ROOT; }; 8363A32E2B4C329100772DDF /* PlaybackInteractorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PlaybackInteractorTests.swift; path = LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift; sourceTree = SOURCE_ROOT; }; + 8363A3322B4D6E9B00772DDF /* MockPlaybackWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPlaybackWorker.swift; sourceTree = ""; }; 836C33862B15A29600ECAFB0 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; 836C338A2B15D22C00ECAFB0 /* PlaybackConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackConfigurator.swift; sourceTree = ""; }; 836C33902B17629400ECAFB0 /* MapRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapRouter.swift; sourceTree = ""; }; @@ -652,6 +654,7 @@ 1925136C2B26F84E001533FA /* MockTagPlayListWorker.swift */, 192513842B27852C001533FA /* MockUserWorker.swift */, 19AE481B2B28C53800DD4612 /* MockSettingWorker.swift */, + 8363A3322B4D6E9B00772DDF /* MockPlaybackWorker.swift */, ); path = Workers; sourceTree = ""; @@ -1602,6 +1605,7 @@ 192513682B26F7CE001533FA /* TagPlayListViewControllerTests.swift in Sources */, 1925136A2B26F7CE001533FA /* TagPlayListWorkerTests.swift in Sources */, 19AE48182B28C2B700DD4612 /* SettingInteractorTests.swift in Sources */, + 8363A3332B4D6E9B00772DDF /* MockPlaybackWorker.swift in Sources */, 192513A72B278BB3001533FA /* Seeds.swift in Sources */, 194C21C52B1DEE6B00C62645 /* HomeWorkerTests.swift in Sources */, 19AE481C2B28C53800DD4612 /* MockSettingWorker.swift in Sources */, diff --git a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift index ef93b5a..c714057 100644 --- a/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift +++ b/iOS/Layover/Layover/Scenes/Playback/PlaybackInteractor.swift @@ -278,7 +278,7 @@ final class PlaybackInteractor: PlaybackBusinessLogic, PlaybackDataStore { isNeedReplace: true) playbackVideoInfos.append(playbackVideoInfos[request.indexPathRow - 1]) if let posts { - self.posts?.insert(posts[request.indexPathRow - 1], at: 0) + self.posts?.append(posts[request.indexPathRow - 1]) } } else { response = Models.DeletePlaybackVideo.Response( diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift new file mode 100644 index 0000000..a8e5d83 --- /dev/null +++ b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift @@ -0,0 +1,177 @@ +// +// MockPlaybackWorker.swift +// Layover +// +// Created by 황지웅 on 12/7/23. +// Copyright © 2023 CodeBomber. All rights reserved. +// + +@testable import Layover +import Foundation +import OSLog + +final class MockPlaybackWorker: PlaybackWorkerProtocol { + + // MARK: - Properties + + typealias Models = PlaybackModels + + private let provider: ProviderType + private let authManager: AuthManagerProtocol + + // MARK: - Methods + + init(provider: ProviderType = Provider(session: .initMockSession()), authManager: AuthManagerProtocol = StubAuthManager()) { + self.provider = provider + self.authManager = authManager + } + + func makeInfiniteScroll(posts: [Post]) -> [Post] { + var tempVideos: [Post] = [] + for post in posts { + if post.board.videoURL == nil { + continue + } + tempVideos.append(post) + } + guard let tempLastVideo: Post = tempVideos.last, + let tempFirstVideo: Post = tempVideos.first + else { return posts } + tempVideos.insert(tempLastVideo, at: 0) + tempVideos.append(tempFirstVideo) + return tempVideos + } + + func deletePlaybackVideo(boardID: Int) async -> Bool { + guard let mockFileLocation = Bundle(for: type(of: self)).url(forResource: "DeleteVideo", withExtension: "json"), + let mockData = try? Data(contentsOf: mockFileLocation) + else { + os_log(.error, log: .data, "Failed to generate mock with error: %@", "Generate File Error") + return false + } + + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse( + url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + do { + let endPoint = EndPoint( + path: "/board", + method: .DELETE, + queryParameters: ["boardId": boardID]) + _ = try await provider.request(with: endPoint) + return true + } catch { + os_log(.error, log: .data, "Failed to delete with error%@", error.localizedDescription) + return false + } + } + + func transLocation(latitude: Double, longitude: Double) async -> String? { + "서울특별시" + } + + func fetchImageData(with url: URL?) async -> Data? { + guard let url else { return nil } + do { + guard let imageURL = Bundle(for: type(of: self)).url(forResource: "sample", withExtension: "jpeg") else { + return nil + } + let mockData = try? Data(contentsOf: imageURL) + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + let data = try await provider.request(url: url) + return data + } catch { + os_log(.error, log: .data, "%@", error.localizedDescription) + return nil + } + } + + func fetchHomePosts() async -> [Post]? { + guard let fileLocation = Bundle(for: type(of: self)).url(forResource: "PostList", withExtension: "json") else { return nil } + do { + let mockData = try Data(contentsOf: fileLocation) + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + let endPoint: EndPoint = EndPoint>(path: "/board/home", + method: .GET) + let response = try await provider.request(with: endPoint) + guard let data = response.data else { return nil } + return data.map { $0.toDomain() } + } catch { + os_log(.error, log: .data, "%@", error.localizedDescription) + return nil + } + } + + func fetchProfilePosts(profileID: Int?, page: Int) async -> [Post]? { + let resourceFileName = switch page { case 1: "PostList" case 2: "PostListMore" default: "PostListEnd" } + guard let fileLocation = Bundle(for: type(of: self)).url(forResource: resourceFileName, withExtension: "json") else { return nil } + do { + let mockData = try Data(contentsOf: fileLocation) + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + let endPoint = EndPoint>(path: "/member/posts", + method: .GET, + queryParameters: ["page": page]) + let response = try await provider.request(with: endPoint) + return response.data?.map { $0.toDomain() } + } catch { + os_log(.error, log: .data, "%@", error.localizedDescription) + return nil + } + } + + func fetchTagPosts(selectedTag: String, page: Int) async -> [Post]? { + let resourceFileName = switch page { case 1: "PostList" case 2: "PostListMore" default: "PostListEnd" } + guard let fileLocation = Bundle(for: type(of: self)).url(forResource: resourceFileName, withExtension: "json") else { return nil } + + do { + let mockData = try? Data(contentsOf: fileLocation) + MockURLProtocol.requestHandler = { request in + let response = HTTPURLResponse(url: request.url!, + statusCode: 200, + httpVersion: nil, + headerFields: nil) + return (response, mockData, nil) + } + + let endPoint = EndPoint>(path: "/board/tag", + method: .GET, + queryParameters: ["tag": selectedTag]) + + let response = try await provider.request(with: endPoint) + return response.data?.map { $0.toDomain() } + } catch { + os_log(.error, log: .data, "%@", error.localizedDescription) + return nil + } + } + + func isMyVideo(currentCellMemberID: Int) -> Bool { + return currentCellMemberID == authManager.memberID + } + +} diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift index 1483b34..2742637 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift @@ -311,43 +311,40 @@ final class PlaybackInteractorTests: XCTestCase { XCTAssertEqual(spy.presentShowPlayerSliderResponse.currentCell, request.currentCell) } -// func test_playVideo를_호출하면_presentMoveCellNext를_호출한다_parentView가_map이고_index가_마지막을_가리킬_떄() { -// // Arrange -// let spy = PlaybackPresentationLogicSpy() -// sut.parentView = .map -// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] -// sut.previousCell = Seeds.PlaybackVideo.previousCell -// let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) -// sut.presenter = spy -// // act -// sut.playVideo(with: request) -// -// // Assert -// XCTAssertTrue(spy.presentTeleportCellDidCalled, "playVideo는 presentTeleportCell를 호출하지 않았습니다") -// XCTAssertEqual(sut.previousCell, Seeds.PlaybackVideo.previousCell) -// XCTAssertEqual(spy.presentTeleportCellResponse.previousCell, Seeds.PlaybackVideo.previousCell) -// XCTAssertEqual(spy.presentTeleportCellResponse.indexPathRow, 1) -// XCTAssertTrue(((sut.isTeleport) != nil)) -// } - -// func test_playVideo를_호출하면_presentMoveCellNext를_호출한다_parentView가_map이고_index가_처음을_가리킬_떄() { -// // Arrange -// let spy = PlaybackPresentationLogicSpy() -// sut.parentView = .map -// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] -// sut.previousCell = Seeds.PlaybackVideo.previousCell -// let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) -// sut.presenter = spy -// // act -// sut.playVideo(with: request) -// -// // Assert -// XCTAssertTrue(spy.presentTeleportCellDidCalled, "playVideo는 presentTeleportCell를 호출하지 않았습니다") -// XCTAssertEqual(spy.presentTeleportCellResponse.previousCell, Seeds.PlaybackVideo.previousCell) -// XCTAssertEqual(spy.presentTeleportCellResponse.currentCell, nil) -// XCTAssertEqual(spy.presentTeleportCellResponse.indexPathRow, 0) -// XCTAssertTrue(((sut.isTeleport) != nil)) -// } + func test_parentView가_map이고_index가_마지막을_가리킬_떄_playVideo를_호출하면_presentMoveCellNext를_호출한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .map + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] + sut.previousCell = Seeds.PlaybackVideo.previousCell + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) + sut.presenter = spy + // act + sut.playVideo(with: request) + + // Assert + XCTAssertTrue(spy.presentMoveCellNextDidCalled, "playVideo는 presentTeleportCell를 호출하지 않았습니다") + XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertFalse(sut.isTeleport!) + } + + func test_parentView가_map이고_index가_처음을_가리킬_떄_playVideo를_호출하면_presentMoveCellNext를_호출한다() { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .map + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] + sut.previousCell = Seeds.PlaybackVideo.previousCell + let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) + sut.presenter = spy + // act + sut.playVideo(with: request) + + // Assert + XCTAssertTrue(spy.presentMoveCellNextDidCalled, "playVideo는 presentTeleportCell를 호출하지 않았습니다") + XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertEqual(spy.presentMoveCellNextResponse.currentCell, Seeds.PlaybackVideo.currentCell) + XCTAssertFalse(sut.isTeleport!) + } func test_playVideo를_호출하면_presentMoveCellNext를_호출한다_parentView가_map이고_텔레포트가_필요없는_상황일_때() { // Arrange @@ -590,63 +587,236 @@ final class PlaybackInteractorTests: XCTestCase { XCTAssertEqual(sut.selectedTag, "테스트") } -// func test_fetchPosts를_호출하면_presentLoadFetchVideosResponse를_호출한다_Home() async { -// // Arrange -// let spy = PlaybackPresentationLogicSpy() -// sut.parentView = .home -// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] -// sut.presenter = spy -// sut.isFetchReqeust = false -// sut.currentPage = 1 -// -// // act -// let result = await sut.fetchPosts().value -// -// // Assert -// XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") -// XCTAssertTrue(result, "fetchPost에 실패했습니다.") -// XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) -// XCTAssertEqual(sut.posts?.count, 3) -// } -// -// func test_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다_tag() async throws { -// // Arrange -// let spy = PlaybackPresentationLogicSpy() -// sut.parentView = .tag -// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2] -// sut.selectedTag = "테스트" -// sut.presenter = spy -// sut.isFetchReqeust = false -// sut.currentPage = 1 -// -// // act -// let result = await sut.fetchPosts().value + func test_Home_fetchPosts를_호출하면_presentLoadFetchVideosResponse를_호출한다() async { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .home + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] + sut.presenter = spy + + // act + await sut.fetchPosts() + + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 3) + } + + func test_tag_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() async throws { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .tag + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2] + sut.playbackVideoInfos = [ + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0) + ] + sut.selectedTag = "테스트" + sut.presenter = spy + + // act + await sut.fetchPosts() // try await Task.sleep(nanoseconds: 3_000_000_000) -// -// // Assert -// XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") -// XCTAssertTrue(result, "fetchPost에 실패했습니다.") -// XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) -// XCTAssertEqual(sut.posts?.count, 21) -// } -// -// func test_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다_Profile() async throws { -// // Arrange -// let spy = PlaybackPresentationLogicSpy() -// sut.parentView = .otherProfile -// sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2] -// sut.presenter = spy -// sut.memberID = -1 -// sut.isFetchReqeust = false -// sut.currentPage = 1 -// -// // act -// let result = await sut.fetchPosts().value -// -// // Assert -// XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") -// XCTAssertTrue(result, "fetchPost에 실패했습니다.") -// XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) -// XCTAssertEqual(sut.posts?.count, 21) -// } + + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 21) + XCTAssertEqual(sut.playbackVideoInfos.count, 21) + } + + func test_Profile_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() async throws { + // Arrange + let spy = PlaybackPresentationLogicSpy() + sut.parentView = .otherProfile + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.post1, Seeds.Posts.post2] + sut.playbackVideoInfos = [ + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0), + Models.PlaybackInfo(memberID: 0, boardID: 0), Models.PlaybackInfo(memberID: 0, boardID: 0) + ] + + sut.presenter = spy + sut.memberID = -1 + + // act + await sut.fetchPosts() + + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 21) + } + + func test_map이_아닐_때_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async throws { + // Arrange + let spy = PlaybackPresentationLogicSpy() + let testPost: Post = Seeds.Posts.post1 + let playbackVideo: Models.PlaybackVideo = Models.PlaybackVideo( + displayedPost: Models.DisplayedPost( + member: Models.Member( + memberID: testPost.member.identifier, + username: testPost.member.username, + profileImageURL: testPost.member.profileImageURL), + board: Models.Board( + boardID: testPost.board.identifier, + title: testPost.board.title, + description: testPost.board.description, + videoURL: testPost.board.videoURL!, + latitude: testPost.board.latitude, + longitude: testPost.board.longitude), + tags: Seeds.Posts.post1.tag)) + sut.parentView = .home + sut.presenter = spy + sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2)] + + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 0)) + + // Assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertTrue(spy.presentDeleteVideoResponse.result) + XCTAssertEqual(spy.presentDeleteVideoResponse.playbackVideo, playbackVideo) + XCTAssertEqual(sut.posts!.count, 1) + XCTAssertEqual(sut.playbackVideoInfos.count, 1) + } + + // TODO: map paging추가되면 로직 그냥 날려버리기 + + func test_map일_때_마지막_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { + // Arrange + let spy = PlaybackPresentationLogicSpy() + let testPost: Post = Seeds.Posts.post1 + let playbackVideo: Models.PlaybackVideo = Models.PlaybackVideo( + displayedPost: Models.DisplayedPost( + member: Models.Member( + memberID: testPost.member.identifier, + username: testPost.member.username, + profileImageURL: testPost.member.profileImageURL), + board: Models.Board( + boardID: testPost.board.identifier, + title: testPost.board.title, + description: testPost.board.description, + videoURL: testPost.board.videoURL!, + latitude: testPost.board.latitude, + longitude: testPost.board.longitude), + tags: Seeds.Posts.post1.tag)) + sut.parentView = .map + sut.presenter = spy + sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] + + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 3)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } + + func test_map일_때_첫번째_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { + // Arrange + let spy = PlaybackPresentationLogicSpy() + let testPost: Post = Seeds.Posts.post1 + let playbackVideo: Models.PlaybackVideo = Models.PlaybackVideo( + displayedPost: Models.DisplayedPost( + member: Models.Member( + memberID: testPost.member.identifier, + username: testPost.member.username, + profileImageURL: testPost.member.profileImageURL), + board: Models.Board( + boardID: testPost.board.identifier, + title: testPost.board.title, + description: testPost.board.description, + videoURL: testPost.board.videoURL!, + latitude: testPost.board.latitude, + longitude: testPost.board.longitude), + tags: Seeds.Posts.post1.tag)) + sut.parentView = .map + sut.presenter = spy + sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] + + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 1)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } + + func test_map일_때_무한스크롤셀을_지우지않을_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { + // Arrange + let spy = PlaybackPresentationLogicSpy() + let testPost: Post = Seeds.Posts.post1 + let playbackVideo: Models.PlaybackVideo = Models.PlaybackVideo( + displayedPost: Models.DisplayedPost( + member: Models.Member( + memberID: testPost.member.identifier, + username: testPost.member.username, + profileImageURL: testPost.member.profileImageURL), + board: Models.Board( + boardID: testPost.board.identifier, + title: testPost.board.title, + description: testPost.board.description, + videoURL: testPost.board.videoURL!, + latitude: testPost.board.latitude, + longitude: testPost.board.longitude), + tags: Seeds.Posts.post1.tag)) + sut.parentView = .map + sut.presenter = spy + sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] + sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] + + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 2)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 1) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } } diff --git a/iOS/Layover/LayoverTests/Seeds.swift b/iOS/Layover/LayoverTests/Seeds.swift index ec3ed8b..b955342 100644 --- a/iOS/Layover/LayoverTests/Seeds.swift +++ b/iOS/Layover/LayoverTests/Seeds.swift @@ -49,7 +49,7 @@ class Seeds { username: "안유진", introduce: "안녕하세요, 아이브의 안유진입니다.", profileImageURL: URL(string: "https://cdn.footballist.co.kr/news/photo/202307/170226_100422_1733.jpg")!), - board: Board(identifier: 1, + board: Board(identifier: 3, title: "최강 아이돌", description: "게시글 설명", thumbnailImageURL: nil, From 9c4623cf433bf71fd04d064c00b05dbc304c2e35 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 11 Jan 2024 00:33:59 +0900 Subject: [PATCH 07/14] =?UTF-8?q?:recycle:=20=EB=A6=AC=EB=B7=B0=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 유경님 리뷰사항 반영 (cherry picked from commit eaa59c03e0b322a413ebc060dafb4b3053f25f4d) --- .../LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift index 2742637..4404170 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift @@ -400,7 +400,7 @@ final class PlaybackInteractorTests: XCTestCase { // Arrange let spy = PlaybackPresentationLogicSpy() sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost] - sut.isTeleport = true + sut.isDelete = true sut.previousCell = Seeds.PlaybackVideo.previousCell let request: Models.DisplayPlaybackVideo.Request = Models.DisplayPlaybackVideo.Request(indexPathRow: 1, currentCell: Seeds.PlaybackVideo.currentCell) sut.presenter = spy @@ -412,7 +412,7 @@ final class PlaybackInteractorTests: XCTestCase { XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, Seeds.PlaybackVideo.previousCell) XCTAssertEqual(spy.presentMoveCellNextResponse.currentCell, Seeds.PlaybackVideo.currentCell) XCTAssertEqual(sut.previousCell, Seeds.PlaybackVideo.currentCell) - XCTAssertFalse(((sut.isDelete) != nil)) + XCTAssertFalse(sut.isDelete!) } func test_resumePlaybackView를_호출할때_previousCell이_존재하면_presentPlayInitialPlaybackCell을_호출한다() { @@ -625,7 +625,6 @@ final class PlaybackInteractorTests: XCTestCase { // act await sut.fetchPosts() -// try await Task.sleep(nanoseconds: 3_000_000_000) // Assert XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") From 2e3bfab1054b91bcc4cf546e8712d6327111a005 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 11 Jan 2024 00:49:16 +0900 Subject: [PATCH 08/14] =?UTF-8?q?:wrench:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=ED=8E=98=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 99445c7e6cb6bbe48d543cf6163033a49e981df0) --- .../LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift index 4404170..aebb427 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift @@ -409,7 +409,7 @@ final class PlaybackInteractorTests: XCTestCase { // Assert XCTAssertTrue(spy.presentMoveCellNextDidCalled, "playTeleportvideo는 presentMoveCellNext를 호출하지 않았습니다") - XCTAssertEqual(spy.presentMoveCellNextResponse.previousCell, Seeds.PlaybackVideo.previousCell) + XCTAssertNil(spy.presentMoveCellNextResponse.previousCell) XCTAssertEqual(spy.presentMoveCellNextResponse.currentCell, Seeds.PlaybackVideo.currentCell) XCTAssertEqual(sut.previousCell, Seeds.PlaybackVideo.currentCell) XCTAssertFalse(sut.isDelete!) From 44b5e7115ab941027b7a9bffb8d8428b71fb0e2c Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 11 Jan 2024 20:25:12 +0900 Subject: [PATCH 09/14] =?UTF-8?q?:recycle:=20Task=20=EA=B0=90=EC=8B=B8?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Workers/PlaybackInteractorTests.swift | 237 ++++++++++-------- 1 file changed, 127 insertions(+), 110 deletions(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift index aebb427..d387b7d 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift @@ -180,45 +180,48 @@ final class PlaybackInteractorTests: XCTestCase { // MARK: - Tests - func test_parentView가_map일_때_displayVideoList를_호출하면_presentVideoList를_호출하고_올바른_데이터를_전달한다() async { + func test_parentView가_map일_때_displayVideoList를_호출하면_presentVideoList를_호출하고_올바른_데이터를_전달한다() { // Arrange let spy = PlaybackPresentationLogicSpy() sut.presenter = spy sut.parentView = .map sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.videoURLNilPost] - // Act - await sut.displayVideoList() + Task { + // Act + await sut.displayVideoList() + + // Assert + XCTAssertTrue(spy.presentVideoListDidCalled, "displayVideoList는 presentVideoList를 호출하지 않았습니다") + // map이므로 2 + 더미셀 2 = 4 + // videoURL이 nil이면 거름 + XCTAssertEqual(spy.presentVideoListResponse.videos.count, 4) + XCTAssertEqual(spy.presentVideoListResponse.videos[0].displayedPost, spy.presentVideoListResponse.videos[2].displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos[1].displayedPost, spy.presentVideoListResponse.videos[1].displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos.first!.displayedPost, Seeds.PlaybackVideos.videos.last!.displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos.last!.displayedPost, Seeds.PlaybackVideos.videos.first!.displayedPost) + } + } - // Assert - XCTAssertTrue(spy.presentVideoListDidCalled, "displayVideoList는 presentVideoList를 호출하지 않았습니다") - // map이므로 2 + 더미셀 2 = 4 - // videoURL이 nil이면 거름 - print(spy.presentVideoListResponse.videos) - XCTAssertEqual(spy.presentVideoListResponse.videos.count, 4) - XCTAssertEqual(spy.presentVideoListResponse.videos[0].displayedPost, spy.presentVideoListResponse.videos[2].displayedPost) - XCTAssertEqual(spy.presentVideoListResponse.videos[1].displayedPost, spy.presentVideoListResponse.videos[1].displayedPost) - XCTAssertEqual(spy.presentVideoListResponse.videos.first!.displayedPost, Seeds.PlaybackVideos.videos.last!.displayedPost) - XCTAssertEqual(spy.presentVideoListResponse.videos.last!.displayedPost, Seeds.PlaybackVideos.videos.first!.displayedPost) - } - - func test_displayVideoList를_호출하면_presentVideoList를_호출하고_올바른_데이터를_전달한다_parentView가_map이_아닐때() async { + func test_displayVideoList를_호출하면_presentVideoList를_호출하고_올바른_데이터를_전달한다_parentView가_map이_아닐때() { // Arrange let spy = PlaybackPresentationLogicSpy() sut.presenter = spy sut.parentView = .home sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.videoURLNilPost] - // Act - await sut.displayVideoList() - - // Assert - XCTAssertTrue(spy.presentVideoListDidCalled, "displayVideoList는 presentVideoList를 호출하지 않았습니다") - // map이므로 2 + 더미셀 2 = 4 - // videoURL이 nil이면 거름 - XCTAssertEqual(spy.presentVideoListResponse.videos.count, 2) - XCTAssertEqual(spy.presentVideoListResponse.videos.first!.displayedPost, Seeds.PlaybackVideos.videos.first!.displayedPost) - XCTAssertEqual(spy.presentVideoListResponse.videos.last!.displayedPost, Seeds.PlaybackVideos.videos.last!.displayedPost) + Task { + // Act + await sut.displayVideoList() + + // Assert + XCTAssertTrue(spy.presentVideoListDidCalled, "displayVideoList는 presentVideoList를 호출하지 않았습니다") + // map이므로 2 + 더미셀 2 = 4 + // videoURL이 nil이면 거름 + XCTAssertEqual(spy.presentVideoListResponse.videos.count, 2) + XCTAssertEqual(spy.presentVideoListResponse.videos.first!.displayedPost, Seeds.PlaybackVideos.videos.first!.displayedPost) + XCTAssertEqual(spy.presentVideoListResponse.videos.last!.displayedPost, Seeds.PlaybackVideos.videos.last!.displayedPost) + } } func test_moveInitialPlaybackCell을_호출하면_presentMoveInitialPlaybackCell을_호출하고_올바른_데이터를_전달한다_parentView가_map일_때() { @@ -587,23 +590,25 @@ final class PlaybackInteractorTests: XCTestCase { XCTAssertEqual(sut.selectedTag, "테스트") } - func test_Home_fetchPosts를_호출하면_presentLoadFetchVideosResponse를_호출한다() async { + func test_Home_fetchPosts를_호출하면_presentLoadFetchVideosResponse를_호출한다() { // Arrange let spy = PlaybackPresentationLogicSpy() sut.parentView = .home sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] sut.presenter = spy - // act - await sut.fetchPosts() + Task { + // act + await sut.fetchPosts() - // Assert - XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") - XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) - XCTAssertEqual(sut.posts?.count, 3) + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 3) + } } - func test_tag_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() async throws { + func test_tag_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() { // Arrange let spy = PlaybackPresentationLogicSpy() sut.parentView = .tag @@ -623,17 +628,19 @@ final class PlaybackInteractorTests: XCTestCase { sut.selectedTag = "테스트" sut.presenter = spy - // act - await sut.fetchPosts() + Task { + // act + await sut.fetchPosts() - // Assert - XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") - XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) - XCTAssertEqual(sut.posts?.count, 21) - XCTAssertEqual(sut.playbackVideoInfos.count, 21) + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 21) + XCTAssertEqual(sut.playbackVideoInfos.count, 21) + } } - func test_Profile_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() async throws { + func test_Profile_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() { // Arrange let spy = PlaybackPresentationLogicSpy() sut.parentView = .otherProfile @@ -654,16 +661,18 @@ final class PlaybackInteractorTests: XCTestCase { sut.presenter = spy sut.memberID = -1 - // act - await sut.fetchPosts() + Task { + // act + await sut.fetchPosts() - // Assert - XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") - XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) - XCTAssertEqual(sut.posts?.count, 21) + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 21) + } } - func test_map이_아닐_때_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async throws { + func test_map이_아닐_때_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -686,20 +695,22 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2)] - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 0)) - - // Assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertTrue(spy.presentDeleteVideoResponse.result) - XCTAssertEqual(spy.presentDeleteVideoResponse.playbackVideo, playbackVideo) - XCTAssertEqual(sut.posts!.count, 1) - XCTAssertEqual(sut.playbackVideoInfos.count, 1) + Task { + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 0)) + + // Assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertTrue(spy.presentDeleteVideoResponse.result) + XCTAssertEqual(spy.presentDeleteVideoResponse.playbackVideo, playbackVideo) + XCTAssertEqual(sut.posts!.count, 1) + XCTAssertEqual(sut.playbackVideoInfos.count, 1) + } } // TODO: map paging추가되면 로직 그냥 날려버리기 - func test_map일_때_마지막_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { + func test_map일_때_마지막_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -722,24 +733,26 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 3)) - - // assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 1) - XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) - XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 1) - XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) - XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.playbackVideoInfos.count, 4) - XCTAssertEqual(sut.posts?.count, 4) - } - - func test_map일_때_첫번째_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { + Task { + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 3)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } + } + + func test_map일_때_첫번째_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -762,24 +775,26 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 1)) - - // assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) - XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) - XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.playbackVideoInfos.count, 4) - XCTAssertEqual(sut.posts?.count, 4) - } - - func test_map일_때_무한스크롤셀을_지우지않을_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { + Task { + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 1)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } + } + + func test_map일_때_무한스크롤셀을_지우지않을_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -802,20 +817,22 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 2)) - - // assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 1) - XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 1) - XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.playbackVideoInfos.count, 4) - XCTAssertEqual(sut.posts?.count, 4) + Task { + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 2)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 1) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } } } From 819bdef8268541775fc6e9ff4ef66f3a8bf42643 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 11 Jan 2024 22:10:00 +0900 Subject: [PATCH 10/14] =?UTF-8?q?:wrench:=20=EB=8B=A4=EC=8B=9C=20Task=20?= =?UTF-8?q?=EB=96=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Workers/PlaybackInteractorTests.swift | 178 ++++++++---------- 1 file changed, 82 insertions(+), 96 deletions(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift index d387b7d..498a737 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift @@ -597,18 +597,16 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] sut.presenter = spy - Task { - // act - await sut.fetchPosts() + // act + await sut.fetchPosts() - // Assert - XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") - XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) - XCTAssertEqual(sut.posts?.count, 3) - } + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 3) } - func test_tag_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() { + func test_tag_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() async { // Arrange let spy = PlaybackPresentationLogicSpy() sut.parentView = .tag @@ -628,19 +626,17 @@ final class PlaybackInteractorTests: XCTestCase { sut.selectedTag = "테스트" sut.presenter = spy - Task { - // act - await sut.fetchPosts() + // act + await sut.fetchPosts() - // Assert - XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") - XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) - XCTAssertEqual(sut.posts?.count, 21) - XCTAssertEqual(sut.playbackVideoInfos.count, 21) - } + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 21) + XCTAssertEqual(sut.playbackVideoInfos.count, 21) } - func test_Profile_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() { + func test_Profile_fetchPosts를_호출하면_presentLoadFetchVideos를_호출한다() async { // Arrange let spy = PlaybackPresentationLogicSpy() sut.parentView = .otherProfile @@ -661,18 +657,16 @@ final class PlaybackInteractorTests: XCTestCase { sut.presenter = spy sut.memberID = -1 - Task { - // act - await sut.fetchPosts() + // act + await sut.fetchPosts() - // Assert - XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") - XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) - XCTAssertEqual(sut.posts?.count, 21) - } + // Assert + XCTAssertTrue(spy.presentLoadFetchVideosDidCalled, "fetchPosts가 presentLoadFetchVideos를 호출하지 않았습니다") + XCTAssertEqual(spy.presentLoadFetchVideosResponse.videos.count, 1) + XCTAssertEqual(sut.posts?.count, 21) } - func test_map이_아닐_때_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { + func test_map이_아닐_때_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -695,22 +689,20 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.post1, Seeds.Posts.post2] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2)] - Task { - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 0)) + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 0)) - // Assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertTrue(spy.presentDeleteVideoResponse.result) - XCTAssertEqual(spy.presentDeleteVideoResponse.playbackVideo, playbackVideo) - XCTAssertEqual(sut.posts!.count, 1) - XCTAssertEqual(sut.playbackVideoInfos.count, 1) - } + // Assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertTrue(spy.presentDeleteVideoResponse.result) + XCTAssertEqual(spy.presentDeleteVideoResponse.playbackVideo, playbackVideo) + XCTAssertEqual(sut.posts!.count, 1) + XCTAssertEqual(sut.playbackVideoInfos.count, 1) } // TODO: map paging추가되면 로직 그냥 날려버리기 - func test_map일_때_마지막_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { + func test_map일_때_마지막_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -733,26 +725,24 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] - Task { - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 3)) - - // assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 1) - XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) - XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 1) - XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) - XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.playbackVideoInfos.count, 4) - XCTAssertEqual(sut.posts?.count, 4) - } - } - - func test_map일_때_첫번째_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 3)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } + + func test_map일_때_첫번째_무한스크롤셀을_지울_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -775,26 +765,24 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] - Task { - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 1)) - - // assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) - XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) - XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) - XCTAssertEqual(sut.playbackVideoInfos.count, 4) - XCTAssertEqual(sut.posts?.count, 4) - } - } - - func test_map일_때_무한스크롤셀을_지우지않을_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() { + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 1)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 2) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 2) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post2.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) + } + + func test_map일_때_무한스크롤셀을_지우지않을_경우_deleteVideo를_호출하면_presentDeleteVideo를_호출한다() async { // Arrange let spy = PlaybackPresentationLogicSpy() let testPost: Post = Seeds.Posts.post1 @@ -817,22 +805,20 @@ final class PlaybackInteractorTests: XCTestCase { sut.posts = [Seeds.Posts.thumbnailImageNilPost, Seeds.Posts.post1, Seeds.Posts.post2, Seeds.Posts.thumbnailImageNilPost ,Seeds.Posts.post1] sut.playbackVideoInfos = [Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1), Models.PlaybackInfo(memberID: 0, boardID: 2), Models.PlaybackInfo(memberID: 0, boardID: 3), Models.PlaybackInfo(memberID: 0, boardID: 1)] - Task { - // act - await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 2)) - - // assert - XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 1) - XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) - XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 1) - XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) - XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post1.board.identifier) - XCTAssertEqual(sut.playbackVideoInfos.count, 4) - XCTAssertEqual(sut.posts?.count, 4) - } + // act + await sut.deleteVideo(with: Models.DeletePlaybackVideo.Request(playbackVideo: playbackVideo, indexPathRow: 2)) + + // assert + XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") + XCTAssertEqual(sut.playbackVideoInfos[0].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[1].boardID, 1) + XCTAssertEqual(sut.playbackVideoInfos[2].boardID, 3) + XCTAssertEqual(sut.playbackVideoInfos[3].boardID, 1) + XCTAssertEqual(sut.posts?[0].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[1].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.posts?[2].board.identifier, Seeds.Posts.thumbnailImageNilPost.board.identifier) + XCTAssertEqual(sut.posts?[3].board.identifier, Seeds.Posts.post1.board.identifier) + XCTAssertEqual(sut.playbackVideoInfos.count, 4) + XCTAssertEqual(sut.posts?.count, 4) } } From f92809424990d7808fbcbbc98f7833d25afe1422 Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 11 Jan 2024 22:12:29 +0900 Subject: [PATCH 11/14] =?UTF-8?q?:wrench:=20async=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Layover.xcodeproj/xcshareddata/xcschemes/Layover.xcscheme | 3 +-- .../LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/iOS/Layover/Layover.xcodeproj/xcshareddata/xcschemes/Layover.xcscheme b/iOS/Layover/Layover.xcodeproj/xcshareddata/xcschemes/Layover.xcscheme index b985a9e..fd553d2 100644 --- a/iOS/Layover/Layover.xcodeproj/xcshareddata/xcschemes/Layover.xcscheme +++ b/iOS/Layover/Layover.xcodeproj/xcshareddata/xcschemes/Layover.xcscheme @@ -30,8 +30,7 @@ shouldAutocreateTestPlan = "YES"> + skipped = "NO"> Date: Thu, 11 Jan 2024 22:46:27 +0900 Subject: [PATCH 12/14] =?UTF-8?q?:wrench:=20MockPlaybackWorker=20init?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Mocks/Workers/MockPlaybackWorker.swift | 14 +++++++------- .../Mocks/Workers/PlaybackInteractorTests.swift | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift index a8e5d83..2ea67a0 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift @@ -16,15 +16,15 @@ final class MockPlaybackWorker: PlaybackWorkerProtocol { typealias Models = PlaybackModels - private let provider: ProviderType - private let authManager: AuthManagerProtocol + private let provider: ProviderType = Provider(session: .initMockSession(), authManager: StubAuthManager()) +// private let authManager: AuthManagerProtocol = StubAuthManager() // MARK: - Methods - init(provider: ProviderType = Provider(session: .initMockSession()), authManager: AuthManagerProtocol = StubAuthManager()) { - self.provider = provider - self.authManager = authManager - } +// init(provider: ProviderType = Provider(session: .initMockSession()), authManager: AuthManagerProtocol = StubAuthManager()) { +// self.provider = provider +// self.authManager = authManager +// } func makeInfiniteScroll(posts: [Post]) -> [Post] { var tempVideos: [Post] = [] @@ -171,7 +171,7 @@ final class MockPlaybackWorker: PlaybackWorkerProtocol { } func isMyVideo(currentCellMemberID: Int) -> Bool { - return currentCellMemberID == authManager.memberID + return true } } diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift index e296766..9e60b17 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/PlaybackInteractorTests.swift @@ -694,7 +694,7 @@ final class PlaybackInteractorTests: XCTestCase { // Assert XCTAssertTrue(spy.presentDeleteVideoDidCalled, "deleteVideo가 presentDeleteVideo를 호출하지 않았습니다") - XCTAssertTrue(spy.presentDeleteVideoResponse.result) + XCTAssertTrue(spy.presentDeleteVideoResponse.result, "result 결과가 옳지 않습니다.") XCTAssertEqual(spy.presentDeleteVideoResponse.playbackVideo, playbackVideo) XCTAssertEqual(sut.posts!.count, 1) XCTAssertEqual(sut.playbackVideoInfos.count, 1) From ed2675575701c61c3be408091baaa09a4ca92f6b Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 11 Jan 2024 22:52:42 +0900 Subject: [PATCH 13/14] =?UTF-8?q?:wrench:=20StubAuthManager=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift index 2ea67a0..81d7928 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift @@ -17,7 +17,7 @@ final class MockPlaybackWorker: PlaybackWorkerProtocol { typealias Models = PlaybackModels private let provider: ProviderType = Provider(session: .initMockSession(), authManager: StubAuthManager()) -// private let authManager: AuthManagerProtocol = StubAuthManager() + private let authManager: AuthManagerProtocol = StubAuthManager() // MARK: - Methods From 7514c1f316ba7a75fd988d7209a09391c77dc0fd Mon Sep 17 00:00:00 2001 From: chopmozzi <44396392+chopmozzi@users.noreply.github.com> Date: Thu, 11 Jan 2024 22:58:40 +0900 Subject: [PATCH 14/14] =?UTF-8?q?:wrench:=20=ED=95=A8=EC=88=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LayoverTests/Mocks/Workers/MockPlaybackWorker.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift index 81d7928..e9d86e9 100644 --- a/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift +++ b/iOS/Layover/LayoverTests/Mocks/Workers/MockPlaybackWorker.swift @@ -21,11 +21,6 @@ final class MockPlaybackWorker: PlaybackWorkerProtocol { // MARK: - Methods -// init(provider: ProviderType = Provider(session: .initMockSession()), authManager: AuthManagerProtocol = StubAuthManager()) { -// self.provider = provider -// self.authManager = authManager -// } - func makeInfiniteScroll(posts: [Post]) -> [Post] { var tempVideos: [Post] = [] for post in posts { @@ -171,7 +166,7 @@ final class MockPlaybackWorker: PlaybackWorkerProtocol { } func isMyVideo(currentCellMemberID: Int) -> Bool { - return true + return currentCellMemberID == authManager.memberID } }