Basic project creation (#3)
This PR contains the work done to create a new *Hummingbird* project with very basic configuration from the _colibri_ executable, just like the project you could create with the [Hummingbird template](https://github.com/hummingbird-project/template) project in Github. Reviewed-on: #3 Co-authored-by: Javier Cicchelli <javier@rock-n-code.com> Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This commit was merged in pull request #3.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import Foundation
|
||||
|
||||
@testable import ColibriLibrary
|
||||
|
||||
extension URL {
|
||||
|
||||
// MARK: Constants
|
||||
|
||||
static let someCurrentFolder = URL(at: "/some/current/folder")
|
||||
static let someDotFolder = URL(at: ".")
|
||||
static let someExistingFolder = URL(at: "/some/existing/folder")
|
||||
static let someExistingFile = URL(at: "/some/existing/file")
|
||||
static let someNewFolder = URL(at: "/some/new/folder")
|
||||
static let someNewFile = URL(at: "/some/new/file")
|
||||
static let someRandomURL = URL(string: "http://some.random.url")!
|
||||
static let someTildeFolder = URL(at: "~")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import ColibriLibrary
|
||||
import Foundation
|
||||
|
||||
final class FileServiceMock {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let folder: URL
|
||||
|
||||
private var actions: [Action] = []
|
||||
|
||||
private weak var spy: FileServiceSpy?
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
init(
|
||||
currentFolder: URL,
|
||||
action: Action? = nil,
|
||||
spy: FileServiceSpy? = nil
|
||||
) {
|
||||
self.actions = if let action {
|
||||
[action]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
self.folder = currentFolder
|
||||
self.spy = spy
|
||||
}
|
||||
|
||||
init(
|
||||
currentFolder: URL,
|
||||
actions: [Action],
|
||||
spy: FileServiceSpy? = nil
|
||||
) {
|
||||
self.actions = actions
|
||||
self.folder = currentFolder
|
||||
self.spy = spy
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - FileServicing
|
||||
|
||||
extension FileServiceMock: FileServicing {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
var currentFolder: URL {
|
||||
get async { folder }
|
||||
}
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
func copyFile(from source: URL, to destination: URL) async throws (FileServiceError) {
|
||||
guard let nextAction else { return }
|
||||
|
||||
switch nextAction {
|
||||
case .error(let error):
|
||||
throw error
|
||||
case let .copyFile(source, destination):
|
||||
try await spy?.copyFile(from: source, to: destination)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func createFolder(at location: URL) async throws (FileServiceError) {
|
||||
guard let nextAction else { return }
|
||||
|
||||
switch nextAction {
|
||||
case .error(let error):
|
||||
throw error
|
||||
case let .createFolder(location):
|
||||
try await spy?.createFolder(at: location)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func deleteItem(at location: URL) async throws (FileServiceError) {
|
||||
guard let nextAction else { return }
|
||||
|
||||
switch nextAction {
|
||||
case .error(let error):
|
||||
throw error
|
||||
case let .deleteItem(location):
|
||||
try await spy?.deleteItem(at: location)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func isItemExists(at location: URL) async throws (FileServiceError) -> Bool {
|
||||
guard let nextAction else { return false }
|
||||
|
||||
switch nextAction {
|
||||
case .error(let error):
|
||||
throw error
|
||||
case let .isItemExists(location, exists):
|
||||
try await spy?.isItemExists(at: location)
|
||||
return exists
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private extension FileServiceMock {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
var nextAction: Action? {
|
||||
guard !actions.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return actions.removeFirst()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
extension FileServiceMock {
|
||||
enum Action {
|
||||
case copyFile(URL, URL)
|
||||
case createFolder(URL)
|
||||
case deleteItem(URL)
|
||||
case error(FileServiceError)
|
||||
case isItemExists(URL, Bool)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import Foundation
|
||||
|
||||
@testable import ColibriLibrary
|
||||
|
||||
final class FileServiceSpy {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private(set) var actions: [Action] = []
|
||||
|
||||
}
|
||||
|
||||
// MARK: - FileServicing
|
||||
|
||||
extension FileServiceSpy: FileServicing {
|
||||
|
||||
var currentFolder: URL {
|
||||
get async { .someCurrentFolder }
|
||||
}
|
||||
|
||||
func copyFile(from source: URL, to destination: URL) async throws (FileServiceError) {
|
||||
actions.append(.fileCopied(source, destination))
|
||||
}
|
||||
|
||||
func createFolder(at location: URL) async throws (FileServiceError) {
|
||||
actions.append(.folderCreated(location))
|
||||
}
|
||||
|
||||
func deleteItem(at location: URL) async throws (FileServiceError) {
|
||||
actions.append(.itemDeleted(location))
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func isItemExists(at location: URL) async throws (FileServiceError) -> Bool {
|
||||
actions.append(.itemExists(location))
|
||||
|
||||
return .random()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Action
|
||||
|
||||
extension FileServiceSpy {
|
||||
enum Action: Equatable {
|
||||
case fileCopied(_ source: URL, _ destination: URL)
|
||||
case folderCreated(_ location: URL)
|
||||
case itemDeleted(_ location: URL)
|
||||
case itemExists(_ location: URL)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user