Template support for input parameters #4
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user