Template support for input parameters #4
@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
public struct FileService: FileServicing {
|
||||
|
||||
public struct FileService {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let fileManager: FileManager
|
||||
@ -12,6 +12,12 @@ public struct FileService: FileServicing {
|
||||
self.fileManager = fileManager
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - FileServicing
|
||||
|
||||
extension FileService: FileServicing {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
public var currentFolder: URL {
|
||||
|
50
Library/Sources/Public/Services/TemplateService.swift
Normal file
50
Library/Sources/Public/Services/TemplateService.swift
Normal file
@ -0,0 +1,50 @@
|
||||
import Foundation
|
||||
import Mustache
|
||||
|
||||
public struct TemplateService {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let mustacheRenderer: MustacheLibrary
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
public init(
|
||||
bundle: Bundleable? = nil,
|
||||
templateFolder: String
|
||||
) async throws (TemplateServiceError) {
|
||||
guard let pathResources = (bundle ?? Bundle.module).resourcePath else {
|
||||
throw .resourcePathNotFound
|
||||
}
|
||||
|
||||
let pathTemplates = pathResources + "/" + templateFolder
|
||||
|
||||
do {
|
||||
self.mustacheRenderer = try await MustacheLibrary(directory: pathTemplates)
|
||||
} catch {
|
||||
throw .serviceNotInitialized
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - TemplateServicing
|
||||
|
||||
extension TemplateService: TemplateServicing {
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
public func render(_ object: Any, on template: String) async throws (TemplateServiceError) -> String {
|
||||
guard mustacheRenderer.getTemplate(named: template) != nil else {
|
||||
throw .templateNotFound
|
||||
}
|
||||
|
||||
guard let content = mustacheRenderer.render(object, withTemplate: template) else {
|
||||
throw .contentNotRendered
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
import ColibriLibrary
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
struct TemplateServiceTests {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private let spy = TemplateServiceSpy()
|
||||
|
||||
// MARK: Functions tests
|
||||
|
||||
@Test(arguments: [String.content])
|
||||
func render(_ content: String) async throws {
|
||||
// GIVEN
|
||||
let service = TemplateServiceMock(action: .render(content), spy: spy)
|
||||
|
||||
// WHEN
|
||||
let result = try await service.render([:], on: .template)
|
||||
|
||||
// THEN
|
||||
#expect(result == content)
|
||||
|
||||
#expect(spy.actions.isEmpty == false)
|
||||
}
|
||||
|
||||
@Test(arguments: [TemplateServiceError.serviceNotInitialized, .resourcePathNotFound, .templateNotFound, .contentNotRendered])
|
||||
func render(throws error: TemplateServiceError) async throws {
|
||||
let service = TemplateServiceMock(action: .error(error), spy: spy)
|
||||
|
||||
// WHEN
|
||||
// THEN
|
||||
await #expect(throws: error) {
|
||||
try await service.render([:], on: .template)
|
||||
}
|
||||
|
||||
#expect(spy.actions.isEmpty == true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - String+Constants
|
||||
|
||||
private extension String {
|
||||
static let content = ""
|
||||
static let template = ""
|
||||
}
|
75
Test/Sources/Helpers/Mocks/TemplateServiceMock.swift
Normal file
75
Test/Sources/Helpers/Mocks/TemplateServiceMock.swift
Normal file
@ -0,0 +1,75 @@
|
||||
import ColibriLibrary
|
||||
import Foundation
|
||||
|
||||
final class TemplateServiceMock {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private var actions: [Action] = []
|
||||
|
||||
private weak var spy: TemplateServiceSpy?
|
||||
|
||||
// MARK: Initialisers
|
||||
|
||||
init(
|
||||
action: Action,
|
||||
spy: TemplateServiceSpy? = nil
|
||||
) {
|
||||
self.actions.append(action)
|
||||
self.spy = spy
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - TemplateServicing
|
||||
|
||||
extension TemplateServiceMock: TemplateServicing {
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
@discardableResult
|
||||
func render(_ object: Any, on template: String) async throws(TemplateServiceError) -> String {
|
||||
guard let nextAction else { return .empty }
|
||||
|
||||
switch nextAction {
|
||||
case .error(let error):
|
||||
throw error
|
||||
case .render(let content):
|
||||
try await spy?.render(object, on: template)
|
||||
return content
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private extension TemplateServiceMock {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
var nextAction: Action? {
|
||||
guard !actions.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return actions.removeFirst()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
extension TemplateServiceMock {
|
||||
enum Action {
|
||||
case error(TemplateServiceError)
|
||||
case render(String)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - String+Constants
|
||||
|
||||
private extension String {
|
||||
static let empty = ""
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import ColibriLibrary
|
||||
import Foundation
|
||||
|
||||
@testable import ColibriLibrary
|
||||
|
||||
final class FileServiceSpy {
|
||||
|
||||
// MARK: Properties
|
||||
|
38
Test/Sources/Helpers/Spies/TemplateServiceSpy.swift
Normal file
38
Test/Sources/Helpers/Spies/TemplateServiceSpy.swift
Normal file
@ -0,0 +1,38 @@
|
||||
import ColibriLibrary
|
||||
|
||||
final class TemplateServiceSpy {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
private(set) var actions: [Action] = []
|
||||
|
||||
}
|
||||
|
||||
// MARK: - TemplateServicing
|
||||
|
||||
extension TemplateServiceSpy: TemplateServicing {
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
@discardableResult
|
||||
func render(_ object: Any, on template: String) async throws(TemplateServiceError) -> String {
|
||||
actions.append(.rendered(object, template))
|
||||
|
||||
return .content
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
extension TemplateServiceSpy {
|
||||
enum Action {
|
||||
case rendered(_ object: Any, _ template: String)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - String+Constants
|
||||
|
||||
private extension String {
|
||||
static let content = ""
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user