Template support for input parameters #4

Merged
javier merged 81 commits from feature/arguments-templating into main 2025-02-17 22:11:06 +00:00
6 changed files with 69 additions and 69 deletions
Showing only changes of commit 26fde119ef - Show all commits

View File

@ -8,9 +8,9 @@ public protocol FileServicing {
// MARK: Functions
func createFolder(at url: URL) async throws (FileServiceError)
func delete(at url: URL) async throws (FileServiceError)
func exists(at url: URL) async throws (FileServiceError) -> Bool
func createFolder(at location: URL) async throws (FileServiceError)
func deleteItem(at location: URL) async throws (FileServiceError)
func isItemExists(at location: URL) async throws (FileServiceError) -> Bool
}
@ -18,8 +18,8 @@ public protocol FileServicing {
public enum FileServiceError: Error, Equatable {
case folderNotCreated
case urlAlreadyExists
case urlNotDeleted
case urlNotExists
case urlNotFileURL
case itemAlreadyExists
case itemNotDeleted
case itemNotExists
case itemNotFileURL
}

View File

@ -22,39 +22,36 @@ public struct FileService: FileServicing {
// MARK: Functions
public func createFolder(at url: URL) async throws (FileServiceError) {
guard try await !exists(at: url) else {
throw FileServiceError.urlAlreadyExists
public func createFolder(at location: URL) async throws (FileServiceError) {
guard try await !isItemExists(at: location) else {
throw FileServiceError.itemAlreadyExists
}
do {
try fileManager.createDirectory(
at: url,
withIntermediateDirectories: true
)
try fileManager.createDirectory(at: location, withIntermediateDirectories: true)
} catch {
throw FileServiceError.folderNotCreated
}
}
public func delete(at url: URL) async throws (FileServiceError) {
guard try await exists(at: url) else {
throw FileServiceError.urlNotExists
public func deleteItem(at location: URL) async throws (FileServiceError) {
guard try await isItemExists(at: location) else {
throw FileServiceError.itemNotExists
}
do {
try fileManager.removeItem(at: url)
try fileManager.removeItem(at: location)
} catch {
throw FileServiceError.urlNotDeleted
throw FileServiceError.itemNotDeleted
}
}
public func exists(at url: URL) async throws (FileServiceError) -> Bool {
guard url.isFileURL else {
throw FileServiceError.urlNotFileURL
public func isItemExists(at location: URL) async throws (FileServiceError) -> Bool {
guard location.isFileURL else {
throw FileServiceError.itemNotFileURL
}
let filePath = url.pathString
let filePath = location.pathString
return fileManager.fileExists(atPath: filePath)
}

View File

@ -27,29 +27,29 @@ struct FileServiceTests {
// MARK: Functions tests
@Test(arguments: [URL.someNewFolder, .someNewFile])
func createFolder(with url: URL) async throws {
func createFolder(with location: URL) async throws {
// GIVEN
let service = FileServiceMock(
currentFolder: .someCurrentFolder,
action: .createFolder(url),
action: .createFolder(location),
spy: spy
)
// WHEN
try await service.createFolder(at: url)
try await service.createFolder(at: location)
// THEN
#expect(spy.actions.count == 1)
let action = try #require(spy.actions.last)
#expect(action == .folderCreated(url))
#expect(action == .folderCreated(location))
}
@Test(arguments: zip([URL.someExistingFolder, .someExistingFile, .someRandomURL],
[FileServiceError.urlAlreadyExists, .urlAlreadyExists, .urlNotFileURL]))
[FileServiceError.itemAlreadyExists, .itemAlreadyExists, .itemNotFileURL]))
func createFolder(
with url: URL,
with location: URL,
throws error: FileServiceError
) async throws {
// GIVEN
@ -62,36 +62,36 @@ struct FileServiceTests {
// WHEN
// THEN
await #expect(throws: error) {
try await service.createFolder(at: url)
try await service.createFolder(at: location)
}
#expect(spy.actions.isEmpty == true)
}
@Test(arguments: [URL.someNewFolder, .someNewFile])
func delete(with url: URL) async throws {
func deleteItem(with location: URL) async throws {
// GIVEN
let service = FileServiceMock(
currentFolder: .someCurrentFolder,
action: .delete(url),
action: .deleteItem(location),
spy: spy
)
// WHEN
try await service.delete(at: url)
try await service.deleteItem(at: location)
// THEN
#expect(spy.actions.count == 1)
let action = try #require(spy.actions.last)
#expect(action == .itemDeleted(url))
#expect(action == .itemDeleted(location))
}
@Test(arguments: zip([URL.someNewFolder, .someNewFile, .someRandomURL],
[FileServiceError.urlNotExists, .urlNotExists, .urlNotFileURL]))
func delete(
with url: URL,
[FileServiceError.itemNotExists, .itemNotExists, .itemNotFileURL]))
func deleteItem(
with location: URL,
throws error: FileServiceError
) async throws {
// GIVEN
@ -104,7 +104,7 @@ struct FileServiceTests {
// WHEN
// THEN
await #expect(throws: error) {
try await service.delete(at: url)
try await service.deleteItem(at: location)
}
#expect(spy.actions.isEmpty == true)
@ -112,31 +112,31 @@ struct FileServiceTests {
@Test(arguments: zip([URL.someExistingFolder, .someExistingFile, .someNewFolder, .someNewFile],
[true, true, false, false]))
func exists(
with url: URL,
func isItemExists(
with location: URL,
expects outcome: Bool
) async throws {
// GIVEN
let service = FileServiceMock(
currentFolder: .someCurrentFolder,
action: .exists(url, outcome),
action: .isItemExists(location, outcome),
spy: spy
)
// WHEN
let result = try await service.exists(at: url)
let result = try await service.isItemExists(at: location)
// THEN
#expect(result == outcome)
let action = try #require(spy.actions.last)
#expect(action == .itemExists(url))
#expect(action == .itemExists(location))
}
@Test(arguments: zip([URL.someRandomURL], [FileServiceError.urlNotFileURL]))
func exists(
with url: URL,
@Test(arguments: zip([URL.someRandomURL], [FileServiceError.itemNotFileURL]))
func isItemExists(
with location: URL,
throws error: FileServiceError
) async throws {
// GIVEN
@ -149,7 +149,7 @@ struct FileServiceTests {
// WHEN
// THEN
await #expect(throws: error) {
try await service.exists(at: url)
try await service.isItemExists(at: location)
}
#expect(spy.actions.isEmpty == true)

View File

@ -36,7 +36,7 @@ struct CreateRootFolderTaskTests {
#expect(result.isFileURL == true)
}
@Test(arguments: [String.someProjectName], [FileServiceError.urlAlreadyExists])
@Test(arguments: [String.someProjectName], [FileServiceError.itemAlreadyExists])
func task(
name: String,
throws error: FileServiceError

View File

@ -42,7 +42,7 @@ final class FileServiceMock {
// MARK: - FileServicing
extension FileServiceMock: FileServicing {
// MARK: Computed
var currentFolder: URL {
@ -51,40 +51,40 @@ extension FileServiceMock: FileServicing {
// MARK: Functions
func createFolder(at url: URL) async throws(FileServiceError) {
func createFolder(at location: URL) async throws (FileServiceError) {
guard let nextAction else { return }
switch nextAction {
case .error(let error):
throw error
case let .createFolder(url):
try await spy?.createFolder(at: url)
case let .createFolder(location):
try await spy?.createFolder(at: location)
default:
break
}
}
func delete(at url: URL) async throws(FileServiceError) {
func deleteItem(at location: URL) async throws (FileServiceError) {
guard let nextAction else { return }
switch nextAction {
case .error(let error):
throw error
case let .delete(url):
try await spy?.delete(at: url)
case let .deleteItem(location):
try await spy?.deleteItem(at: location)
default:
break
}
}
func exists(at url: URL) async throws(FileServiceError) -> Bool {
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 .exists(url, exists):
try await spy?.exists(at: url)
case let .isItemExists(location, exists):
try await spy?.isItemExists(at: location)
return exists
default:
return false
@ -114,8 +114,8 @@ private extension FileServiceMock {
extension FileServiceMock {
enum Action {
case createFolder(URL)
case delete(URL)
case deleteItem(URL)
case error(FileServiceError)
case exists(URL, Bool)
case isItemExists(URL, Bool)
}
}

View File

@ -13,21 +13,24 @@ final class FileServiceSpy {
// MARK: - FileServicing
extension FileServiceSpy: FileServicing {
var currentFolder: URL {
get async { .someCurrentFolder }
}
func createFolder(at url: URL) async throws (FileServiceError) {
actions.append(.folderCreated(url))
}
func delete(at url: URL) async throws (FileServiceError) {
actions.append(.itemDeleted(url))
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 exists(at url: URL) async throws (FileServiceError) -> Bool {
actions.append(.itemExists(url))
func isItemExists(at location: URL) async throws (FileServiceError) -> Bool {
actions.append(.itemExists(location))
return .random()
}
@ -38,8 +41,8 @@ extension FileServiceSpy: FileServicing {
extension FileServiceSpy {
enum Action: Equatable {
case folderCreated(_ url: URL)
case itemDeleted(_ url: URL)
case itemExists(_ url: URL)
case folderCreated(_ location: URL)
case itemDeleted(_ location: URL)
case itemExists(_ location: URL)
}
}