Skip to content

Commit

Permalink
Add IInternalXcodeProject protocol for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
swiftyfinch committed Nov 8, 2023
1 parent 6db41f0 commit 7de0fc6
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 20 deletions.
4 changes: 2 additions & 2 deletions Sources/RugbyFoundation/Core/Build/BuildManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ final class BuildManager: Loggable {
let logger: ILogger
private let buildTargetsManager: BuildTargetsManager
private let librariesPatcher: ILibrariesPatcher
private let xcodeProject: XcodeProject
private let xcodeProject: IInternalXcodeProject
private let rugbyXcodeProject: RugbyXcodeProject
private let backupManager: IBackupManager
private let processMonitor: IProcessMonitor
Expand All @@ -49,7 +49,7 @@ final class BuildManager: Loggable {
init(logger: ILogger,
buildTargetsManager: BuildTargetsManager,
librariesPatcher: ILibrariesPatcher,
xcodeProject: XcodeProject,
xcodeProject: IInternalXcodeProject,
rugbyXcodeProject: RugbyXcodeProject,
backupManager: IBackupManager,
processMonitor: IProcessMonitor,
Expand Down
4 changes: 2 additions & 2 deletions Sources/RugbyFoundation/Core/Build/BuildTargetsManager.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Foundation

final class BuildTargetsManager {
private let xcodeProject: XcodeProject
private let xcodeProject: IInternalXcodeProject
private let buildTargetName = "RugbyPods"

init(xcodeProject: XcodeProject) {
init(xcodeProject: IInternalXcodeProject) {
self.xcodeProject = xcodeProject
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ enum RugbyError: LocalizedError {
// MARK: - Implementation

final class RugbyXcodeProject {
private let xcodeProject: XcodeProject
private let xcodeProject: IInternalXcodeProject
private let yes = "YES"

init(xcodeProject: XcodeProject) {
init(xcodeProject: IInternalXcodeProject) {
self.xcodeProject = xcodeProject
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ public protocol IDeleteTargetsManager {

final class DeleteTargetsManager: Loggable {
let logger: ILogger
private let xcodeProject: XcodeProject
private let xcodeProject: IInternalXcodeProject
private let backupManager: IBackupManager

init(logger: ILogger,
xcodeProject: XcodeProject,
xcodeProject: IInternalXcodeProject,
backupManager: IBackupManager) {
self.logger = logger
self.xcodeProject = xcodeProject
Expand Down
4 changes: 2 additions & 2 deletions Sources/RugbyFoundation/Core/Rollback/BackupManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public protocol IBackupManager {
/// - Parameters:
/// - xcodeProject: A service for Xcode project managment.
/// - kind: The type of backup.
func backup(_ xcodeProject: XcodeProject, kind: BackupKind) async throws
func backup(_ xcodeProject: IXcodeProject, kind: BackupKind) async throws

/// Restores Xcode project.
/// - Parameter kind: The type of backup.
Expand Down Expand Up @@ -146,7 +146,7 @@ extension BackupManager {
// MARK: - IBackupManager

extension BackupManager: IBackupManager {
public func backup(_ xcodeProject: XcodeProject, kind: BackupKind) async throws {
public func backup(_ xcodeProject: IXcodeProject, kind: BackupKind) async throws {
let projects = try await xcodeProject.folderPaths().map(Folder.at)
switch kind {
case .original:
Expand Down
4 changes: 2 additions & 2 deletions Sources/RugbyFoundation/Core/Use/UseBinariesManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class UseBinariesManager: Loggable {

private let buildTargetsManager: BuildTargetsManager
private let librariesPatcher: ILibrariesPatcher
private let xcodeProject: XcodeProject
private let xcodeProject: IInternalXcodeProject
private let rugbyXcodeProject: RugbyXcodeProject
private let backupManager: IBackupManager
private let binariesManager: IBinariesStorage
Expand All @@ -41,7 +41,7 @@ final class UseBinariesManager: Loggable {
init(logger: ILogger,
buildTargetsManager: BuildTargetsManager,
librariesPatcher: ILibrariesPatcher,
xcodeProject: XcodeProject,
xcodeProject: IInternalXcodeProject,
rugbyXcodeProject: RugbyXcodeProject,
backupManager: IBackupManager,
binariesManager: IBinariesStorage,
Expand Down
2 changes: 1 addition & 1 deletion Sources/RugbyFoundation/Vault/Commands/Vault+Use.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extension Vault {
}

func useBinariesManager(workingDirectory: IFolder,
xcodeProject: XcodeProject,
xcodeProject: IInternalXcodeProject,
buildTargetsManager: BuildTargetsManager) -> IUseBinariesManager {
UseBinariesManager(logger: logger,
buildTargetsManager: buildTargetsManager,
Expand Down
4 changes: 2 additions & 2 deletions Sources/RugbyFoundation/Vault/Common/XcodeVault.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public final class XcodeVault {
private let logsRotator: LogsRotator
private let router: Router

private var xcodeProjectsCache: [String: XcodeProject] = [:]
private var xcodeProjectsCache: [String: IInternalXcodeProject] = [:]

// MARK: - Init

Expand Down Expand Up @@ -44,7 +44,7 @@ public final class XcodeVault {

// MARK: - Internal Methods

func project(projectPath: String) -> XcodeProject {
func project(projectPath: String) -> IInternalXcodeProject {
if let cachedXcodeProject = xcodeProjectsCache[projectPath] { return cachedXcodeProject }

let projectDataSource = XcodeProjectDataSource(logger: logger, projectPath: projectPath)
Expand Down
57 changes: 52 additions & 5 deletions Sources/RugbyFoundation/XcodeProject/XcodeProject.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,56 @@
import Foundation

/// The service for Xcode project managment.
public final class XcodeProject {
/// The protocol describing a service for Xcode project managment.
public protocol IXcodeProject: AnyObject {
/// Returns paths to folders with root project and subprojects.
func folderPaths() async throws -> [String]
/// Returns `true` if the root project contains the key in the build settings.
func contains(buildSettingsKey: String) async throws -> Bool
/// Sets the value to the key in the build settings of the root project.
func set(buildSettingsKey: String, value: Any) async throws
}

protocol IInternalXcodeProject: IXcodeProject {
func resetCache()
func save() async throws

func findTargets(
by regex: NSRegularExpression?,
except exceptRegex: NSRegularExpression?,
includingDependencies: Bool
) async throws -> TargetsMap

func createAggregatedTarget(
name: String,
dependencies: TargetsMap
) async throws -> IInternalTarget

func deleteTargets(
_ targetsForRemove: TargetsMap,
keepGroups: Bool
) async throws
}

// MARK: - Implementation

extension IInternalXcodeProject {
func findTargets() async throws -> TargetsMap {
try await findTargets(by: nil, except: nil, includingDependencies: false)
}

func findTargets(
by regex: NSRegularExpression?,
except exceptRegex: NSRegularExpression?
) async throws -> TargetsMap {
try await findTargets(by: regex, except: exceptRegex, includingDependencies: false)
}

func deleteTargets(_ targetsForRemove: TargetsMap) async throws {
try await deleteTargets(targetsForRemove, keepGroups: true)
}
}

final class XcodeProject {
private let projectDataSource: XcodeProjectDataSource
private let targetsFinder: XcodeTargetsFinder
private let targetsEditor: XcodeTargetsEditor
Expand All @@ -18,9 +67,7 @@ public final class XcodeProject {
}
}

// MARK: - Implementation

extension XcodeProject {
extension XcodeProject: IInternalXcodeProject {
// MARK: - File System

func folderPaths() async throws -> [String] {
Expand Down
168 changes: 168 additions & 0 deletions Tests/FoundationTests/Mocks/IInternalXcodeProjectMock.generated.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Generated using Sourcery 2.1.1 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT

// swiftlint:disable all

import Foundation
@testable import RugbyFoundation

final class IInternalXcodeProjectMock: IInternalXcodeProject {

// MARK: - resetCache

var resetCacheCallsCount = 0
var resetCacheCalled: Bool { resetCacheCallsCount > 0 }
var resetCacheClosure: (() -> Void)?

func resetCache() {
resetCacheCallsCount += 1
resetCacheClosure?()
}

// MARK: - save

var saveThrowableError: Error?
var saveCallsCount = 0
var saveCalled: Bool { saveCallsCount > 0 }
var saveClosure: (() async throws -> Void)?

func save() async throws {
if let error = saveThrowableError {
throw error
}
saveCallsCount += 1
try await saveClosure?()
}

// MARK: - findTargets

var findTargetsByExceptIncludingDependenciesThrowableError: Error?
var findTargetsByExceptIncludingDependenciesCallsCount = 0
var findTargetsByExceptIncludingDependenciesCalled: Bool { findTargetsByExceptIncludingDependenciesCallsCount > 0 }
var findTargetsByExceptIncludingDependenciesReceivedArguments: (regex: NSRegularExpression?, exceptRegex: NSRegularExpression?, includingDependencies: Bool)?
var findTargetsByExceptIncludingDependenciesReceivedInvocations: [(regex: NSRegularExpression?, exceptRegex: NSRegularExpression?, includingDependencies: Bool)] = []
var findTargetsByExceptIncludingDependenciesReturnValue: TargetsMap!
var findTargetsByExceptIncludingDependenciesClosure: ((NSRegularExpression?, NSRegularExpression?, Bool) async throws -> TargetsMap)?

func findTargets(by regex: NSRegularExpression?, except exceptRegex: NSRegularExpression?, includingDependencies: Bool) async throws -> TargetsMap {
if let error = findTargetsByExceptIncludingDependenciesThrowableError {
throw error
}
findTargetsByExceptIncludingDependenciesCallsCount += 1
findTargetsByExceptIncludingDependenciesReceivedArguments = (regex: regex, exceptRegex: exceptRegex, includingDependencies: includingDependencies)
findTargetsByExceptIncludingDependenciesReceivedInvocations.append((regex: regex, exceptRegex: exceptRegex, includingDependencies: includingDependencies))
if let findTargetsByExceptIncludingDependenciesClosure = findTargetsByExceptIncludingDependenciesClosure {
return try await findTargetsByExceptIncludingDependenciesClosure(regex, exceptRegex, includingDependencies)
} else {
return findTargetsByExceptIncludingDependenciesReturnValue
}
}

// MARK: - createAggregatedTarget

var createAggregatedTargetNameDependenciesThrowableError: Error?
var createAggregatedTargetNameDependenciesCallsCount = 0
var createAggregatedTargetNameDependenciesCalled: Bool { createAggregatedTargetNameDependenciesCallsCount > 0 }
var createAggregatedTargetNameDependenciesReceivedArguments: (name: String, dependencies: TargetsMap)?
var createAggregatedTargetNameDependenciesReceivedInvocations: [(name: String, dependencies: TargetsMap)] = []
var createAggregatedTargetNameDependenciesReturnValue: IInternalTarget!
var createAggregatedTargetNameDependenciesClosure: ((String, TargetsMap) async throws -> IInternalTarget)?

func createAggregatedTarget(name: String, dependencies: TargetsMap) async throws -> IInternalTarget {
if let error = createAggregatedTargetNameDependenciesThrowableError {
throw error
}
createAggregatedTargetNameDependenciesCallsCount += 1
createAggregatedTargetNameDependenciesReceivedArguments = (name: name, dependencies: dependencies)
createAggregatedTargetNameDependenciesReceivedInvocations.append((name: name, dependencies: dependencies))
if let createAggregatedTargetNameDependenciesClosure = createAggregatedTargetNameDependenciesClosure {
return try await createAggregatedTargetNameDependenciesClosure(name, dependencies)
} else {
return createAggregatedTargetNameDependenciesReturnValue
}
}

// MARK: - deleteTargets

var deleteTargetsKeepGroupsThrowableError: Error?
var deleteTargetsKeepGroupsCallsCount = 0
var deleteTargetsKeepGroupsCalled: Bool { deleteTargetsKeepGroupsCallsCount > 0 }
var deleteTargetsKeepGroupsReceivedArguments: (targetsForRemove: TargetsMap, keepGroups: Bool)?
var deleteTargetsKeepGroupsReceivedInvocations: [(targetsForRemove: TargetsMap, keepGroups: Bool)] = []
var deleteTargetsKeepGroupsClosure: ((TargetsMap, Bool) async throws -> Void)?

func deleteTargets(_ targetsForRemove: TargetsMap, keepGroups: Bool) async throws {
if let error = deleteTargetsKeepGroupsThrowableError {
throw error
}
deleteTargetsKeepGroupsCallsCount += 1
deleteTargetsKeepGroupsReceivedArguments = (targetsForRemove: targetsForRemove, keepGroups: keepGroups)
deleteTargetsKeepGroupsReceivedInvocations.append((targetsForRemove: targetsForRemove, keepGroups: keepGroups))
try await deleteTargetsKeepGroupsClosure?(targetsForRemove, keepGroups)
}

// MARK: - folderPaths

public var folderPathsThrowableError: Error?
public var folderPathsCallsCount = 0
public var folderPathsCalled: Bool { folderPathsCallsCount > 0 }
public var folderPathsReturnValue: [String]!
public var folderPathsClosure: (() async throws -> [String])?

public func folderPaths() async throws -> [String] {
if let error = folderPathsThrowableError {
throw error
}
folderPathsCallsCount += 1
if let folderPathsClosure = folderPathsClosure {
return try await folderPathsClosure()
} else {
return folderPathsReturnValue
}
}

// MARK: - contains

public var containsBuildSettingsKeyThrowableError: Error?
public var containsBuildSettingsKeyCallsCount = 0
public var containsBuildSettingsKeyCalled: Bool { containsBuildSettingsKeyCallsCount > 0 }
public var containsBuildSettingsKeyReceivedBuildSettingsKey: String?
public var containsBuildSettingsKeyReceivedInvocations: [String] = []
public var containsBuildSettingsKeyReturnValue: Bool!
public var containsBuildSettingsKeyClosure: ((String) async throws -> Bool)?

public func contains(buildSettingsKey: String) async throws -> Bool {
if let error = containsBuildSettingsKeyThrowableError {
throw error
}
containsBuildSettingsKeyCallsCount += 1
containsBuildSettingsKeyReceivedBuildSettingsKey = buildSettingsKey
containsBuildSettingsKeyReceivedInvocations.append(buildSettingsKey)
if let containsBuildSettingsKeyClosure = containsBuildSettingsKeyClosure {
return try await containsBuildSettingsKeyClosure(buildSettingsKey)
} else {
return containsBuildSettingsKeyReturnValue
}
}

// MARK: - set

public var setBuildSettingsKeyValueThrowableError: Error?
public var setBuildSettingsKeyValueCallsCount = 0
public var setBuildSettingsKeyValueCalled: Bool { setBuildSettingsKeyValueCallsCount > 0 }
public var setBuildSettingsKeyValueReceivedArguments: (buildSettingsKey: String, value: Any)?
public var setBuildSettingsKeyValueReceivedInvocations: [(buildSettingsKey: String, value: Any)] = []
public var setBuildSettingsKeyValueClosure: ((String, Any) async throws -> Void)?

public func set(buildSettingsKey: String, value: Any) async throws {
if let error = setBuildSettingsKeyValueThrowableError {
throw error
}
setBuildSettingsKeyValueCallsCount += 1
setBuildSettingsKeyValueReceivedArguments = (buildSettingsKey: buildSettingsKey, value: value)
setBuildSettingsKeyValueReceivedInvocations.append((buildSettingsKey: buildSettingsKey, value: value))
try await setBuildSettingsKeyValueClosure?(buildSettingsKey, value)
}
}

// swiftlint:enable all

0 comments on commit 7de0fc6

Please sign in to comment.